Create a Moq of a concrete class with dependencies - c#

I have a concrete class CalculatorService of which I want to test CalculateBuyOrder() method. CalculatorService has several dependencies injected through constructor parameters and CalculateBuyOrder() calls another method on the same service.
I need a mock of the class that
Can be created without parameterless constructor (i.e., automatically mocking the dependency tree).
Has all methods mocked (stubbed) by default, with the option of overriding and calling the real implementation on one (or several) methods.
It seems such an obvious and basic use case, but I can't seem to neither figure it out myself nor find the documentation that explains it. The furthest I've gotten is using AutoMocker for achieving 1., but 2. has me stumped.
public class CalculatorService
: ICalculatorService
{
private readonly IMainDbContext _db;
private readonly TradeConfig _tradeConfig;
private readonly MainConfig _config;
private readonly StateConfig _state;
private readonly ICurrencyService _currencyService;
private readonly IExchangeClientService _client;
// Parameters need to be mocked
public CalculatorService(MainDbContext db, TradeConfig tradeConfig, MainConfig config, StateConfig state, ICurrencyService currencyService, IExchangeClientService client)
{
this._db = db;
this._tradeConfig = tradeConfig;
this._config = config;
this._state = state;
this._currencyService = currencyService;
this._client = client;
}
// This needs to be tested
public async Task<OrderDto> CalculateBuyOrder(
String coin,
CoinPriceDto currentPrice,
Decimal owned,
IDictionary<TradeDirection, OrderDto> lastOrders,
OrderDto existingOrder = null,
TradeConfig.TradeCurrencyConfig tradingTarget = null,
Decimal? invested = null)
{
// ...
this.GetInvested();
// ...
}
// This needs to be mocked
public virtual IDictionary<String, Decimal> GetInvested()
{
// ...
}
}
}

As some of the comments have said you should place interfaces in your constructor as for an example pseudo code:
public class Foo : IFoo
{
IBoo boo;
IGoo goo;
public Foo(IBoo boo, IGoo goo)
{
this.boo = boo;
this.goo = goo;
}
public int MethodToTest(int num1,int num2)
{
//some code
/*..*/ = boo.Method(num1,num2);
//more code and return
}
}
notice all the parameters in the constructor are interfaces.
and then your test method would look a little like this
[TestMethod]
public void TestMethod()
{
//setting up test
var boo = new Mock<IBoo>();
var goo = new Mock<IGoo>();
var foo = new Foo(boo.object,goo.object);
boo.Setup(x=>x.Method(1,2)).Returns(10);
//running test
var result = foo.MethodToTest(1,2);
//verify the test
Assert.AreEqual(12,result);
}
For more information just go to this link Moq Github.
Now for the second part of your question, mocking a method within the same class. This defeats the purpose of mocking, as mocking is to "fake" dependencies. So either restructure the code so you can mock it properly, or make sure any methods it calls are mocked in a way they'll give a reliable output that you can use.

Related

Set up Private variable in Class for Nunit Test

I'm trying to write a unit test for a class but the class has a Private variable initiated when the class is created..
public class OrderFormService : IOrderFormService
{
private readonly IOrderItems _orderItems;
private readonly string _orderStartingGroup;
// constructor
public OrderFormService(IOrderItems orderItems)
{
_orderItems = orderItems;
_orderStartingGroup = "Sales";
{
// Other Methods
}
I'm trying to write a unit test now and to test a method in this class and it utilises the variable _orderStartingGroup...
[TestFixture]
public class OrderFormServiceTests
{
private ITreatmentFormService _service;
private Mock<IOrderItems> _orderItems;
[SetUp]
public void SetUp()
{
_orderItems = new Mock<IOrderItems>();
_service = new OrderFormService(_orderItems);
}
}
Is it possible to set up the _orderStartingGroup in OrderFormServiceTest so it can be used in unit tests for testing some methods in OrderFormService? If so, how do I go about it? I've tried googling it but results keep talking about accessing private variables in the class you're testing but this isn't what I'm trying to do.
Thanks in advance :)
Well even if there is a way of setting private field directly from unit test method it’ll break an architectural principle or two..
There are a few ways of how to deal with this problem. The simplest solution would be to change the ctor signature by adding an optional parameter:
// constructor
public OrderFormService(IOrderItems orderItems, string orderStartingGroup = null)
{
_orderItems = orderItems;
_orderStartingGroup = orderStartingGroup ?? "Sales";
{
And use it in unit test:
[SetUp]
public void SetUp()
{
_orderItems = new Mock<IOrderItems>();
_service = new OrderFormService(_orderItems, “testValue”);
}
I think this might an indicator that you are doing something wrong. I would rather focus on public interfaces rather than testing internal implementation. If this somehow reflected in public interface there should be a way to set it via public interface or convention (say read from a config file).
But if you absolutely need to do that, you can consider following:
Use fabjan's answer
Set private field value with reflection
Make this private member as protected and create an derived test class.

Use mock.Provide() to Setup a delegate factory, used in the SUT constructor

I am trying to test the behavior of a class, when it's passed one stub object via a delegate factory. I made a version of the test in which all the class's dependencies (except the factory) are passed as Mock objects and it works as supposed to. Now I am trying to use AutoMock to get the container to automatically create the mocks.
I am having issues passing concrete values for the delegate factory in the constructor in ClassUnderTest using mock.Provide(). (like this comment suggests)
Class that I am testing:
public ClassUnderTest
{
private readonly firstField;
private readonly Func<string, ISecondField, IThirdField, IResultField> resultFieldFactory;
private int someCounter = -1;
public ClassUnderTest(IFirstField firstField, Func<string, ISecondField, IThirdField, IResultField> resultFieldFactory )
{
this.firstField = firstField;
this.resultFieldFactory= resultFieldFactory;
}
public methodToTest()
{
IResultField resultField = resultFieldFactory(someString, secondFieldValue, thirdFieldValue);
resultField.AddToList();
}
}
Business logic module :
public class BusinessLogicModule: Module
{
//some other things that work
builder.RegisterType<ClassUnderTest>().As<IClassUnderTest>();
builder.RegisterType<SecondField>().As<ISecondField>();
builder.RegisterType<ThirdField>().As<IThirdField>();
builder.RegisterType<ResultField>().As<IResultField>();
}
Test class:
[TestClass]
public class TestClass()
{
private IFirstField firstField;
private Func<string, ISecondField, IThirdField, IResultField> funcToTriggerIResultFieldFactory;
[TestInitialize]
public void Setup()
{
this.firstField= Resolve<IFirstField>();
this.secondField= Resolve<ISecondField>();
this.funcToTriggerIResultFieldFactory = Resolve<Func<string, ISecondField, IThirdField, IResultField>>();
}
[TestMethod]
public void testMethodWithAutoMock()
{
using (var automock = AutoMock.GetLoose())
{
//trying to setup the SUT to get passed a "concrete" object
autoMock.Provide(funcToTriggerIResultFieldFactory(stringValue, secondFieldValue, thirdFieldValue));
var sut = autoMock.Create<IClassUnderTest>;
sut.MethodToTest();
//asserts
}
}
}
I would be grateful for any indication on what I am doing wrong. What am I missing? How could it be fixed? Is it a simple syntax fix or is something wrong with my approach to this test?
Thanks in advance for your time.
In your example, when you call autoMock.Provide() you are not passing in you factory function, but you are invoking the factory function and passing in the result (IResultField). To fix this, call
autoMock.Provide(funcToTriggerIResultFieldFactory);
Here is a full example of registering a function with the auto mocking container.

How to use Moq on singleton classes so that we can only test Business logic and ignore logging

public class SLogger
{
private const string SSchemasFileName = "sSchemas";
private const string SLogsFileName = "sLogs";
private static string logsDir = #"D:\Data\logs\local\";
private static readonly Lazy<SLogger> instance = new Lazy<SLogger>(() => new SLogger());
private ESC eSC;
private AEL aEL;
private SllLogger()
{
eSC= new ESC(logsDir , SSchemasFileName);
aEL= new AEL(logsDir , SLogsFileName, EventLevel.Verbose);
}
public static SLogger Instance
{
get
{
return instance.Value;
}
}
public void LogInformation()
{
// Some logic here
}
}
How can I use Moq framework to just test the business logic and ignore the logging library code?
For example if I have some class which has a method as shown below and I want to unit test this method using Moq framework or any other framework then how can I Moq this singleton class?
Is there any other way I can do it?
void foo()
{
// Business logic
SLogger.Instance.LogInformation();
// Business logic
}
Without having an abstraction to depend on instead of a tight coupling to SLogger, there's no way to test foo() independently.
I'd suggest you define an interface for SLogger to implement; minimally, given your example:
public interface ILogger
{
void LogInformation();
}
I'd further suggest you provide an instance of ILogger in your class' constructor, as a form of dependency injection, and have your class invoke methods of the injected dependency:
public class Bar
{
private readonly ILogger _logger;
public Bar(ILogger logger)
{
_logger = logger;
}
public void Foo()
{
_logger.LogInformation();
}
}
From your calling code, you can now provide a real implementation of ILogger, be it a singleton instance of SLogger, or a mock for a unit test:
//Real call
var myBar = new Bar(SLogger.Instance);
//From a test
var testBar = new Bar(new Mock<ILogger>().Object);
There are plenty of resources across Stack Overflow and on the web to learn about dependency injection and inversion of control patterns, but Mark Seemann's blog is a good starting point.

How to type cast interface to a concrete type

I am trying to mock the ManagementObjectSearcher class and have created a IManagementInfo interface, so how can i cast the interface to the ManagementObjectSearcher class?
ManagementObjectSearcher s = new ManagementObjectSearcher();
IManagementInfo info = s as IManagementInfo;
this creates me a null info object
ManagementObjectSearcher s = new ManagementObjectSearcher();
IManagementInfo info =IManagementInfo(s);
this gives me run time error (cannot typecast)
You cannot do that. Do you want to do it so that you can write unit tests? If you are trying to mock a class that you have no control of, then you have to wrap it in another class.
public class MyManagementObjectSearcherWrapper : IManagementInfo
{
public void TheMethodToMock()
{
var searcher = new ManagementObjectSearcher();
// The code you want to mock goes here
}
}
And you run your code like this:
public void YourCode(IManagementInfo info)
{
info.TheMethodToMock();
}
Then YourCode() will take either your wrapper or the mocked object. You create your mock using the IManagementInfo interface.
It looks as if you are trying to wrap a 3rd party/system object in order to aid unit testing.
Say that your starting point is
public class Dependency {
public string Foo() {
return "foo"; // machine, system, time, something else, dependent result
}
public string Bar() {
return "bar";
}
}
public class MySimpleClass {
public string MyFunc() {
return new Dependency().Foo();
}
}
[TestMethod]
public void TestSimple() {
var client = new MySimpleClass();
Assert.AreEqual("foo", client.MyFunc());
}
We are creating the Dependency inside the call because we are considering the creation cost to be less important than holding on to an instance of the Dependency. This will be dependent upon the situation. We could as easily have created a Dependency in the ctor and stored a copy which we invoked each time. Either way, we have no control over the output which makes unit testing messy.
We need to create a proxy for it.
1. Define an interface for the members that we need
Most likely, we do not need to use all of the members of the wrappee so only include in the interface those about which we care.
public interface IDependencyProxy {
string Foo();
}
2. Create a Proxy Class
We then create a proxy class wrapping the dependency and implementing interface. Again, we can create at start or on a call by call basis.
public class DependencyProxy : IDependencyProxy {
public string Foo() {
return new Dependency.Foo();
}
}
3. Define our client code in terms of the interface
We modify our client code slightly to use the IDependencyProxy interface instead of the Dependency. There are a few ways of doing this. I generally use an internal ctor which takes the dependency chained from a public ctor. (Use [InternalsVisibleTo] to allow the unit tests to see it)
public class MyRevisedClass {
private readonly IDependencyProxy dependency;
public MyRevisedClass()
: this( new DependencyProxy()) {}
internal MyRevisedClass(IDependencyProxy dependency) {
this.dependency = dependency;
}
public string MyFunc() {
return dependency.Foo();
}
}
This allows us a default behaviour for the production code (invokes the System object) and allows us to mock out the results for unit testing.
[TestMethod]
public void TestRevisedDefault() {
var client = new MyRevisedClass();
Assert.AreEqual("foo", client.MyFunc());
}
[TestMethod]
public void TestRevisedWithMockedDependency() {
var dep = new Mock<IDependencyProxy>();
dep.Setup(mk => mk.Foo()).Returns("bar");
var client = new MyRevisedClass(dep.Object);
Assert.AreEqual("bar", client.MyFunc());
}

NSubstitute mock generic method

I have the following method signature in an interface:
public interface ISettingsUtil
{
T GetConfig<T>(string setting, dynamic settings);
}
Which I have attempted to mock:
var settingsUtil = Substitute.For<ISettingsUtil>();
var maxImageSize = settingsUtil.GetConfig<long>("maxImageSize",
Arg.Any<dynamic>()).Returns(100L);
This throws a Microsoft.CSharp.RuntimeBinder.RuntimeBinderException exception on the 2nd line:
'long' does not contain a definition for 'Returns'
Any thoughts on how to mock T GetConfig<T>(string setting, dynamic settings) correctly?
For anyone still struggling with this, you can actually mock dynamics in NSubsitute, it just requires jumping through some minor hoops.
See the below case of mocking out calls to a signalR client hub.
The important line is this one:
SubstituteExtensions.Returns(_hubContext.Clients.All, _mockClient);
In order to mock the dynamic I have created an interface with the methods I want to listen for. You then need to use SubstituteExtensions.Returns rather than simply chaining a .Returns at the end of the object.
If you don't need to verify anything you could also use an anonymous object.
Full code sample follows:
[TestFixture]
public class FooHubFixture
{
private IConnectionManager _connectionManager;
private IHubContext _hubContext;
private IMockClient _mockClient;
[SetUp]
public void SetUp()
{
_hubContext = Substitute.For<IHubContext>();
_connectionManager = Substitute.For<IConnectionManager>();
_connectionManager.GetHubContext<FooHub>().Returns(_hubContext);
_mockClient = Substitute.For<IMockClient>();
SubstituteExtensions.Returns(_hubContext.Clients.All, _mockClient);
}
[Test]
public void PushFooUpdateToHub_CallsUpdateFooOnHubClients()
{
var fooDto = new FooDto();
var hub = new FooHub(_connectionManager);
hub.PushFooUpdateToHub(fooDto);
_mockClient.Received().updateFoo(fooDto);
}
public interface IMockClient
{
void updateFoo(object val);
}
}
public class FooHub : Hub
{
private readonly IConnectionManager _connectionManager;
public FooHub(IConnectionManager connectionManager)
{
_connectionManager = connectionManager;
}
public void PushFooUpdateToHub(FooDto fooDto)
{
var context = _connectionManager.GetHubContext<FooHub>();
context.Clients.All.updateFoo(fooDto);
}
}
NSubstitute does not work with members that use dynamic. (Github issue)

Categories