Mock a method of class under test with Moq & AutoMock - c#

I've been reading around and I can't seem to find a case that matches the behavior I want with Moq.
I want to mock a specific method (which is interfacing with an external API) of a class that I want to test. The problem is that, as I understand it, once the class is .Create<T>, you cannot .Setup()... any method on it.
Here is an example:
public class ClassA
{
public void ConfigureExpansion()
{
var classB = new ClassB();
var data = GetExternalData(); // I want to mock this
//data is used in the code
classB.TaskB(data); // I want to mock this
}
public string GetExternalData()
{
return data...
}
}
public class ClassB
{
public void TaskB(String myData)
{
//Does some work
}
}
[TestMethod]
public void Test()
{
using (var mock = AutoMock.GetLoose())
{
mock.Mock<IClassB>().Setup(x => x.TaskB(It.IsAny<string>()));
var cls = mock.Create<ClassA>();
cls.Setup(x => x.GetExternalData(It.IsAny<string>())).Return("MyData"); // <--- This is not valid, but represents what I am trying to do.
//act
cls.ConfigureExpansion();
mock.Mock<IClassB>().Verify(x => x.TaskB(), Times.Once);
}
}
I tried to set up a mock for the interface of my class under test, but the cls won't call it:
[TestMethod]
public void Test()
{
using (var mock = AutoMock.GetLoose())
{
mock.Mock<IClassA>().Setup(x => x.GetExternalData(It.IsAny<string>())).Return("MyData"); //<--- Mocking the method here is not detected by the cls below
mock.Mock<IClassB>().Setup(x => x.TaskB(It.IsAny<string>()));
var cls = mock.Create<ClassA>();
//act
cls.ConfigureExpansion();
mock.Mock<IClassB>().Verify(x => x.TaskB(), Times.Once);
}
}
I've also tried instantiating my class-under-test and when I do it like this, it doesn't take the mocks (ClassB) into consideration:
[TestMethod]
public void Test()
{
using (var mock = AutoMock.GetLoose())
{
mock.Mock<IClassA>().Setup(x => x.GetExternalData(It.IsAny<string>())).Return("MyData"); //<--- Mocking the method here is not detected by the cls below
mock.Mock<IClassB>().Setup(x => x.TaskB(It.IsAny<string>()));
var cls = new ClassA();
//act
cls.ConfigureExpansion();
mock.Mock<IClassB>().Verify(x => x.TaskB(), Times.Once);
}
}
I would really appreciate any insights about this,
Thank you

Here is one approach for your problem. If you want to test ConfigureExpansion of ClassA, you have to mock the dependencies used in that method, which is ClassB. You cannot mock GetExternalData of ClassA because ClassA is the class under test now. You may have to refactor your classes in a way so that there is a ClassUnderTest which creates both instances of ClassA and ClassB using dependency injection. Then, you can use Moq to mock the interfaces IClassA and IClassB to test the ConfigureExpansion.
public class ClassUnderTest
{
private readonly IClassA _classA;
private readonly IClassB _classB;
public ClassUnderTest(IClassA classA, IClassB classB)
{
this._classA = classA;
this._classB = classB;
}
public void ConfigureExpansion()
{
var data = this._classA.GetExternalData();
this._classB.TaskB(data);
}
}
public interface IClassA
{
string GetExternalData();
}
public class ClassA : IClassA
{
public string GetExternalData()
{
return "some data";
}
}
public interface IClassB
{
void TaskB(string myData);
}
public class ClassB : IClassB
{
public void TaskB(string myData)
{
//Does some work
}
}
The test method can be:
[TestMethod]
public void Test()
{
using (var mock = AutoMock.GetLoose())
{
var mockClassA = mock.Mock<IClassA>();
var mockClassB = mock.Mock<IClassB>();
mockClassA.Setup(x => x.GetExternalData()).Returns("MyData");
var cls = new ClassUnderTest(mockClassA.Object, mockClassB.Object);
//act
cls.ConfigureExpansion();
mockClassB.Verify(x => x.TaskB(It.IsAny<string>()), Times.Once);
}
}

Related

xUnit test: How to mock a factory?

I have the follwing two classes ClassA and ClassB.
To focus on: ClassB implements a factory of ClassA.
I want to test ClassB. So how can I (or would you) mock a factory of ClassA, sothat ClassB can instantiate a mock of ClassA and access its mocked function .ReturnString()?
public class ClassA : IClassA
{
readonly int _number;
public ClassA(int number)
{
_number = number;
}
public string ReturnString()
{
return _number.ToString();
}
}
public class ClassB : IClassB
{
int _exampleValue;
readonly Func<int, IClassA> _classAFactory;
public ClassB(Func<int, IClassA> classAFactory)
{
_classAFactory = classAFactory;
}
public string ExampleFct()
{
_exampleValue = 5;
IClassA classA = _classAFactory(_exampleValue)
return classA.ReturnString();
}
}
public class TestClassB
{
[Fact]
public void TestClassBReturnsCorrectString()
{
// Arrange
var mockClassAFact = ???
IClassB classB = new ClassB(mockClassAFact);
// Act
string aString = classB.ExampleFct();
// Assert
Assert.True(aString == "5");
}
}
As I am using "Autofac" as a base for IoC there might be a specific solution for this?
Thank you for any help!
mock the dependency (interface) as desired and create a delegate for the "factory" when arranging the test
[Fact]
public void TestClassBReturnsCorrectString() {
// Arrange
string expected = "5"
IClassA mockClassA = Mock.Of<IClassA>(_ => _.ReturnString() == expected);
int value = 5;
Func<int, IClassA> mockClassAFact =
number => number == value ? mockClassA : throw new InvalidArgumentException();
IClassB subject = new ClassB(mockClassAFact);
// Act
string actual = subject.ExampleFct();
// Assert
Assert.True(actual == expected);
}
Note: The above example uses MOQ to mock the IClassA dependency and creates a factory delegate to be used to exercised the test.
"Autofac" in this case is an implementation detail that has no actual bearing on this isolated unit test.

Other than mocked method call actual methods for a mock object

IFoo
{
string abc();
string def();
}
Foo: IFoo
{
string abc()
{
def();
}
string def()
{
}
}
Mymainclass
{
private IFoo _foo;
public Mymainclass():this(new Foo())
{}
public Mymainclass(IFoo foo)
{
_foo = foo;
}
string mainmethod()
{
_foo.abc();
}
}
[TestClass]
public class Mymainclasstester
{
Mymainclass mainclass;
Mock<IFoo> mifoo;
[TestInitialize]
public void TestInitialize()
{
mifoo = new Mock<IFoo>();
mifoo.Setup(x => x.def(It.IsAny<string>())).Returns("abc");
mainclass = new Mymainclass(mifoo.Object);
}
[TestMethod]
public void testmethod()
{
mainclass.mainmethod();
}
}
As seen above in the testmethod() i am calling mainmethod() of class Mymainclass, which inturn calls abc() of Foo class.
abc() makes call to def() as it can be seen in the above code. I have mocked only def().
When the call is made from testmethod() i want to make an actual call to abc() of Foo, and mock only def().
Currently with this implementation abc() is not executing.
Can anyone help me on this?
You cannot archive what you want using interface. Actually, you can but by mocking abc to invoke def which seems a bit awkward:
mock.Setup(x => x.abc()).Returns(() => mock.Object.def());
Although I don't see the point here, you could just mock abc instead...
The only way to archive what you want using mock is by using actual class and Callbase feature.
public class Foo : IFoo
{
public virtual string abc() //methods have to be virtual to be mockable
{
return def();
}
public virtual string def() //methods have to be virtual to be mockable
{
return "123";
}
}
//setup
var mock = new Mock<Foo>();
mock.Setup(x => x.def()).Returns("abc");
mock.Setup(x => x.abc()).CallBase();
mock.Object.abc(); // "abc"
In this case, you are setting up the actual class instead of the interface so you need to refactor a bit your implementation. Not sure if this is the right approach just the way how to implement your requirement.

Partial mock methods in a class using Autofixture, Moq and XUnit

I want to mock only some methods of a class and call the real implementation for other methods.
I have my sut class Test where the Runner class is injected in the constructor. This injected class has again a injected other class RunnerParam in the constructor.
The code is a simplified case of my real classes in trying to have only the basics.
[Fact]
public void Test()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var paramMock = fixture.Freeze<Mock<IRunnerParam>>();
paramMock.Setup(x => x.Multiplicator()).Returns(2);
var classMock = fixture.Freeze<Mock<IRunner>>();
classMock.Setup(x => x.Run()).Returns(5);
var test = fixture.Create<Test>();
var result = test.StartRunning(); // should be 5
var result2 = test.StartRunningImplementation(5); // should be 500
}
Supporting members
public interface IRunnerParam
{
int Multiplicator();
}
public class RunnerParam : IRunnerParam
{
public virtual int Multiplicator()
{
return 20;
}
}
public interface IRunner
{
int Run();
int RunImplementation(int param);
}
public class Runner : IRunner
{
protected virtual RunnerParam MultiParam { get; set; }
public Runner(RunnerParam multiParam)
{
MultiParam = multiParam;
}
public virtual int Run()
{
return 10;
}
public int RunImplementation(int param)
{
return 10 * MultiParam.Multiplicator() * param * Run();
}
}
public class Test
{
private readonly IRunner _runner;
public Test(IRunner runner)
{
_runner = runner;
}
public int StartRunning()
{
return _runner.Run();
}
public int StartRunningImplementation(int param)
{
return _runner.RunImplementation(param);
}
}
I want to mock and give a mocked value to the method Run in the class Runner, but to use the real implementation of the method RunImplementation.
I would expect to see for result2 500, but it's 0, meaning that the method is not seen as mocked up. In my eyes that is correct, but the Moq callbase is equal to true, so the real implementation should be taken, but it isn't.
What am I missing here?
In the shown simplified example, Test is only dependent on IRunner
private readonly IRunner _runner;
public Test(IRunner runner)
{
_runner = runner;
}
So that is all that needs to be mocked if the intention was to test Test class in isolation.
//...
var classMock = fixture.Freeze<Mock<IRunner>>();
classMock.Setup(x => x.Run()).Returns(5);
classMock.Setup(x => x.RunImplementation(It.IsAny<int>())).Returns(500);
//...
If Runner class is to be also tested in isolation, then a mocked RunnerParam would be needed to satisfy its dependencies.
It should however be dependent on the abstraction (interface) and not the concretion (implementation).
protected virtual IRunnerParam MultiParam { get; set; }
public Runner(IRunnerParam multiParam) {
MultiParam = multiParam;
}
This simplifies the isolated test as described in the original question
I want to mock and give a mocked value to the method Run in the class Runner, but to use the real implementation of the method RunImplementation.
//Arrange
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var runnerParam = fixture.Freeze<Mock<IRunnerParam>>()
.Setup(_ => _.Multiplicator())
.Returns(2);
var subjectMock = fixture.Freeze<Mock<Runner>>();
subjectMock.CallBase = true;
subjectMock.Setup(_ => _.Run()).Returns(5);
int expected = 500;
Runner sut = subjectMock.Object;
//Act
var actual = sut.RunImplementation(5); // should be 500
//Assert
actual.Should().Be(expected);

Mock certain part of the method using Moq

I'm new to Moq and I would like to mock certain part of my method to test the business logic but having problem to mock the GetCountry method. Below is the code that I used as sample.
public class Class1
{
public void Process()
{
MyClass foo = new MyClass();
var o = foo.GetCountry(); //I would like to mock this part.
//Business Logic here
}
}
public class MyClass : IFoo
{
public List<string> GetCountry()
{
//Get the data from Database.. someone will do this
throw new NotImplementedException();
}
}
Below is my Test Code that I used.
[TestMethod]
public void TestMethod2()
{
var mock = new Moq.Mock<IFoo>();
mock.Setup(m => m.GetCountry()).Returns(new List<string> { "America", "Philippines", "Japan" });
ClassLibrary1.Class1 foo = new ClassLibrary1.Class1();
//still called the not implemented exception
foo.Process();
}
Your code currently doesn't have an easy way to replace one implementation to another. Try this approach:
public class Class1
{
// Instead of using a concrete class, use an interface
// also, promote it to field
IFoo _foo;
// Create a constructor that accepts the interface
public Class1(IFoo foo)
{
_foo = foo;
}
// alternatively use constructor which provides a default implementation
public Class1() : this(new MyClass())
{
}
public void Process()
{
// Don't initialize foo variable here
var o = _foo.GetCountry();
//Business Logic here
}
}
If you have such setup it is quite easy to mock it using your code:
[TestMethod]
public void TestMethod2()
{
var mock = new Moq.Mock<IFoo>();
mock.Setup(m => m.GetCountry()).Returns(new List<string> { "America", "Philippines", "Japan" });
// Pass mocked object to your constructor:
ClassLibrary1.Class1 foo = new ClassLibrary1.Class1(mock.Object);
foo.Process();
}

Assertion of void asynchronous method

I have a class similiar to this:
public class MyClass
{
public Task MyMethod()
{
//do something
}
}
As described, 'MyMethod' is asynchronous, lets say for simplicity that this is it's implementation:
public Task MyMethod()
{
return Task.Run(() =>
{
var success = _someService.DoSomething();
if (!success) throw new Exception("unsuccsesfull");
});
}
Obviously, when MyMethod awaitable callback will run it means that no exception was thrown in the running thread, meaning 'MyMethod' invocation was successfull.
I want to test this method. The test method to will look like:
[Test]
public async void TestMyMethod_TestInitialState_TestExpectedResult()
{
// test initialization..
//...
//..
var myClass = new MyClass();
await myClass.MyMethod();
Assert.That(????)
}
My question - what is the correct assertion?
I have a possible solution - add a logical member to 'MyClass' and update this member according to the method result:
public class MyClass
{
public bool SomeMember { get; private set; }
public Task MyMethod()
{
Task.Run(() =>
{
SomeMember = _someService.DoSomething();
if (!SomeMember ) throw new Exception("unsuccsesfull");
});
}
}
That way I can assert the test like this:
[Test]
public async void TestMyMethod_TestInitialState_SomeMemberShouldBeTrue()
{
// test initialization..
//...
//..
var myClass = new MyClass();
await myClass.MyMethod();
Assert.True(SomeMember)
}
}
However, I dont like this solution because I'm adding a property to 'MyClass' just to be able to assert a test, I dont really need this property in my bussiness world. Also each property added to a class represents some state of this class and adds a level of comlexity.
Suggestions?
Guy.
You want what's called a "mock" or "stub". The idea is that you refactor your code so that it has a dependency on an interface, then you mock the interface while testing.
There are various frameworks/tools that help out with mocking (Moq, Microsoft Fakes, TypeMock Isolator, JustMock, etc), and there are also many frameworks that help out with the closely related problem of dependency injection (Unity, Castle Windsor, StructureMap, Autofac, etc).
But you can start off just doing it yourself. First, refactor MyClass so it depends on ISomeService:
public interface ISomeService
{
bool DoSomething();
}
public class MyClass
{
private readonly ISomeService _someService;
public MyClass(ISomeService someService)
{
_someService = someService;
}
public Task MyMethod()
{
return Task.Run(() =>
{
var success = _someService.DoSomething();
if (!success) throw new Exception("unsuccsesfull");
});
}
}
Then in your unit test:
private class TestService : ISomeService
{
public bool DoSomethingReturnValue { get; set; }
public bool DoSomething() { return DoSomethingReturnValue; }
}
[Test]
public async Task TestMyMethod_TestInitialState_TestExpectedResult()
{
var myClass = new MyClass(new TestService { DoSomethingReturnValue = true });
await myClass.MyMethod();
}
[Test]
public async Task TestMyMethod_TestInitialState_TestFailure()
{
var myClass = new MyClass(new TestService { DoSomethingReturnValue = false });
Assert.Throws(() => myClass.MyMethod()); // (I'm unsure of the exact NUnit syntax)
}

Categories