Here is a very simplistic example of what I'm trying to do:
public class Bar
{
public void SomeMethod(string param)
{
//whatever
}
}
public interface IBarRepository
{
List<Bar> GetBarsFromStore();
}
public class FooService
{
private readonly IBarRepository _barRepository;
public FooService(IBarRepository barRepository)
{
_barRepository = barRepository;
}
public List<Bar> GetBars()
{
var bars = _barRepository.GetBarsFromStore();
foreach (var bar in bars)
{
bar.SomeMethod("someValue");
}
return bars;
}
}
In my test, I'm mocking IBarRepository to return a concrete List defined in the unit test and passing that mocked repository instance to the FooService constructor.
I want to verify in the FooService method GetBars that SomeMethod was called for each of the Bars returned from the repository. I'm using Moq. Is there any way to do this without mocking the list of Bars returned (if even possible) and not having to put some hacky flag in Bar (yuck) ?.
I'm following an example from a DDD book, but I'm starting to think it smells because I'm challenged in testing the implementation....
Revised... this passes:
public class Bar
{
public virtual void SomeMethod(string param)
{
//whatever
}
}
public interface IBarRepository
{
List<Bar> GetBarsFromStore();
}
public class FooService
{
private readonly IBarRepository _barRepository;
public FooService(IBarRepository barRepository)
{
_barRepository = barRepository;
}
public List<Bar> GetBars()
{
var bars = _barRepository.GetBarsFromStore();
foreach (var bar in bars)
{
bar.SomeMethod("someValue");
}
return bars;
}
}
[TestMethod]
public void Verify_All_Bars_Called()
{
var myBarStub = new Mock<Bar>();
var mySecondBarStub = new Mock<Bar>();
var myBarList = new List<Bar>() { myBarStub.Object, mySecondBarStub.Object };
var myStub = new Mock<IBarRepository>();
myStub.Setup(repos => repos.GetBarsFromStore()).Returns(myBarList);
var myService = new FooService(myStub.Object);
myService.GetBars();
myBarStub.Verify(bar => bar.SomeMethod(It.IsAny<string>()), Times.Once());
mySecondBarStub.Verify(bar => bar.SomeMethod(It.IsAny<string>()), Times.Once());
}
Note the slight change to class Bar (SomeMethod() is virtual). A change, but not one involving a flag... :)
Now, in terms of broader design, there is some mutation going on with your bar (whatever "SomeMethod()" actually does). The best thing to do would probably be to verify that this mutation happened on each Bar returned from FooService.GetBars(). That is, setup your repository stub to return some bars, and then verify that whatever mutation is performed by SomeMethod() has taken place. After all, you control the Bars that will be returned, so you can setup their pre-SomeMethod() state, and then inspect their post-SomeMethod() state.
If I was writing these classes with unit testing in mind, I would likely either have the class Bar implement an interface IBar and use that interface in my service, or make SomeMethod virtual in Bar.
Ideally like this:
public interface IBar
{
void SomeMethod(string param);
}
public class Bar : IBar
{
public void SomeMethod(string param) {}
}
public interface IBarRepository
{
List<IBar> GetBarsFromStore();
}
public class FooService
{
private readonly IBarRepository _barRepository;
public FooService(IBarRepository barRepository)
{
_barRepository = barRepository;
}
public List<IBar> GetBars()
{
var bars = _barRepository.GetBarsFromStore();
foreach (var bar in bars)
{
bar.SomeMethod("someValue");
}
return bars;
}
}
Then my unit test would look as follows:
[Test]
public void TestSomeMethodCalledForEachBar()
{
// Setup
var barMocks = new Mock<IBar>[] { new Mock<IBar>(), new Mock<IBar>() };
var barObjects = barMocks.Select(m => m.Object);
var repoList = new List<IBar>(barsObjects);
var repositoryMock = new Mock<IBarRepository>();
repositoryMock.Setup(r => r.GetBarsFromStore()).Returns(repoList);
// Execute
var service = new FooService(repositoryMock.Object);
service.GetBars();
// Assert
foreach(var barMock in barMocks)
barMock.Verify(b => b.SomeMethod("someValue"));
}
Related
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);
}
}
Not sure I am doing this correctly but essentially I have an object Foo which has heaps of configurations. I am using the Fluent Builder pattern to set the params as it makes it easier to mix & match. Once the parameters are set I wish to essentially "run" the analysis...
The complication is with the Bar object which is a slightly different calculation method uses a combined set of the Foo params + Bar params.
My initial thoughts is to have an abstract calculation class BaseCalc which contains common calculations and set either FooCalc or BarCalc which contains the custom calculations depending if AddBar is called.
analysis = new FooBuilder()
.SetData(data)
.SetParam1("Foo")
.AddBar(builder => builder
.SetParam2("Bar")
)
.Build();
public class FooBuilder: IFooBuilder
{
private readonly Foo foo;
public IFooBuilder SetData(List<int> data)
{
foo.source = data;
return this;
}
public IFooBuilder SetParam1(string param)
{
foo.param1 = param;
return this;
}
public IFooBuilder(AddBar(Action<IBarBuilder> configure)
{
var builder = new BarBuilder();
configure(builder);
foo.Bar = builder.Build();
return this;
}
}
public abstract class BaseCalc
{
public abstract void Run();
}
public class FooCalc : BaseCalc
{
public override void Run()
{
Console.WriteLine("This should be Param1 Foo");
}
}
public class BarCalc : BaseCalc
{
public override void Run()
{
Console.WriteLine("This should be Param1 Foo + Param2 Bar");
}
}
As an example if I called analysis.Run() in the example above it would run BarCalc.Run() using both Foo and Bar
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.
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();
}
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)
}