I have a service class as below:
public class MyService
{
private readonly IMyDependency _myDependency;
public MyService(IMyDependency myDependency)
{
_myDependency = myDependency;
}
public void MyHandler(string param)
{
// work
}
public void AnotherMethod()
{
_myDependency.DoWork(MyHandler);
}
}
How can I Unit Test that MyHandler has been given as a parameter of DoWork()?
Since you are using Moq, you can write test like this:
[TestMethod]
public void DoWorkWasCalledWithCorrectParameters()
{
var mock = new Moq.Mock<IMyDependency>();
var myService = new MyService(mock.Object);
myService.AnotherMethod();
// verify that method was called once and with correct parameter:
mock.Verify(x => x.DoWork(myService.MyHandler), Moq.Times.Once);
}
Related
I have an interface with a method like this:
public string GetImageSrc(string input);
The implementation of this is below:
public string GetImageSrc(string input)
{
if (input.ContainsImage())
{
DoWork();
}
return input;
}
My string extension for ConatinsImage is:
public static bool ContainsImage(this string input)
{
if (!string.IsNullOrEmpty(input))
{
return input.Contains("img");
}
return false;
}
DoWork is a private method in the class. I am writing Unit Tests for the class - I am passing null to the method and doing an assert that null is returned. However is there a way I can Assert the invocation of the DoWork private method is None for a null input?
I recommend creating a new interface IWorker with a DoWork() method, then inject it into the constructor of the class that contains the GetImageSrc() method. In your unit test, you could then inject a mock object of the interface, and verify DoWork() was called or not:
public interface IWorker
{
void DoWork();
}
public class YourClass
{
private readonly IWorker _worker;
public YourClass(IWorker worker)
{
_worker = worker;
}
public string GetImageSrc(string input)
{
if (input.ContainsImage())
{
_worker.DoWork();
}
return input;
}
}
Test using Microsoft.VisualStudio.TestTools.UnitTesting and Moq:
[TestMethod]
public void GetImageSrc_GivenNull_ReturnsNull_And_WorkerNotCalled()
{
var mockWorker = new Mock<IWorker>();
var testSubject = new YourClass(mockWorker.Object);
var response = testSubject.GetImageSrc(null);
Assert.IsNull(response);
mockWorker.Verify(x => x.DoWork(), Times.Never());
}
I have an abstract class that I want to test. There is an abstract property in this class for my DAO, which I define in inherited classes.
public abstract class DeviceGroupManagerBase<TDeviceGroup> where TDeviceGroup : DeviceGroup
{
protected abstract IDeviceGroupDao<TDeviceGroup> DeviceGroupDao { get; }
public TDeviceGroup UpdateDeviceIndexes(Device device)
{
return DeviceGroupDao.GetDeviceGroup(device.Group.Id);
}
}
I want to test the Updatedeviceindexes method so I'm trying to mock a property called DeviceGroupDao.
[TestFixture]
[Category("Unit")]
public class DeviceGroupManagerBaseTests
{
private IFixture fixture;
private Mock<DeviceGroupManagerBase<DeviceGroup>> subject;
private Mock<IDeviceGroupDao<DeviceGroup>> deviceGroupDaoMock;
private DeviceGroupManagerBase<DeviceGroup> Manager => subject.Object;
[TestFixtureSetUp]
public void Init()
{
fixture = new Fixture().Customize(new AutoMoqCustomization());
deviceGroupDaoMock = fixture.Freeze<Mock<IDeviceGroupDao<DeviceGroup>>>();
subject = fixture.Freeze<Mock<DeviceGroupManagerBase<DeviceGroup>>>();
}
[Test]
public void TestUpdateDeviceIndexes()
{
var device = fixture.Create<Device>();
var deviceGroup = fixture.Create<DeviceGroup>();
deviceGroupDaoMock.Setup(x => x.GetDeviceGroup(It.IsAny<int>())).Returns(deviceGroup);
var result = Manager.UpdateDeviceIndexes(device);
// The resultDeviceGroup will not be contain a previously defined object
Assert.AreEqual(deviceGroup.Id, result.Id);
}
}
I also tried to add registration for my device object in this way:
fixture.Register(() => deviceGroup);
But I'm still getting a new object.
How can I mock IDeviceGroupDao<TDeviceGroup>?
Since DeviceGroupManagerBase is an abstract base class, you'll need a SUT Double. It's easiest to do if you make the DeviceGroupDao property public:
public abstract class DeviceGroupManagerBase<TDeviceGroup> where TDeviceGroup : DeviceGroup
{
public abstract IDeviceGroupDao<TDeviceGroup> DeviceGroupDao { get; }
public TDeviceGroup UpdateDeviceIndexes(Device device)
{
return DeviceGroupDao.GetDeviceGroup(device.Group.Id);
}
}
Otherwise, you'll need to use Moq's API for defining and overriding protected members, which is possible, but more work.
Then you'll need to override subject's DeviceGroupDao property:
subject.SetupGet(x => x.DeviceGroupDao).Returns(deviceGroupDaoMock.Object);
Here's the full test:
[TestFixture]
[Category("Unit")]
public class DeviceGroupManagerBaseTests
{
private IFixture fixture;
private Mock<DeviceGroupManagerBase<DeviceGroup>> subject;
private Mock<IDeviceGroupDao<DeviceGroup>> deviceGroupDaoMock;
private DeviceGroupManagerBase<DeviceGroup> Manager => subject.Object;
[OneTimeSetUp]
public void Init()
{
fixture = new Fixture().Customize(new AutoMoqCustomization());
deviceGroupDaoMock = fixture.Freeze<Mock<IDeviceGroupDao<DeviceGroup>>>();
subject = fixture.Freeze<Mock<DeviceGroupManagerBase<DeviceGroup>>>();
subject.SetupGet(x => x.DeviceGroupDao).Returns(deviceGroupDaoMock.Object);
}
[Test]
public void TestUpdateDeviceIndexes()
{
var device = fixture.Create<Device>();
var deviceGroup = fixture.Create<DeviceGroup>();
deviceGroupDaoMock.Setup(x => x.GetDeviceGroup(It.IsAny<int>())).Returns(deviceGroup);
var result = Manager.UpdateDeviceIndexes(device);
Assert.AreEqual(deviceGroup.Id, result.Id);
}
}
This now passes on my machine.
Because the DeviceGroupDao is protected you will need to find a way to access it externally. Create a stub that would allow you set it value.
public class DeviceGroupManagerBaseStub<TDeviceGroup>
: DeviceGroupManagerBase<TDeviceGroup> where TDeviceGroup : DeviceGroup {
private IDeviceGroupDao<TDeviceGroup> deviceGroupDao;
public DeviceGroupManagerBaseStub(IDeviceGroupDao<TDeviceGroup> deviceGroupDao) {
this.deviceGroupDao = deviceGroupDao;
}
protected override IDeviceGroupDao<TDeviceGroup> DeviceGroupDao {
get {
return deviceGroupDao;
}
}
}
You can then mock IDeviceGroupDao<TDeviceGroup> and inject it into the stub for your test.
Please see the code below:
[TestClass]
public class UnitTest1
{
Moq.Mock<ISayGoodMorning> GoodMorningMock;
[TestInitialize]
public void init()
{
GoodMorningMock = new Moq.Mock<ISayGoodMorning>();
GoodMorningMock.Setup(x => x.GoodMorning()).Returns(Test());
}
[TestMethod]
public void TestMethod1()
{
GoodMorningMock.Verify(x => x.GoodMorning(), Times.Once());
Assert.AreEqual(g.SayGreeting(), "Hola");
}
public string Test()
{
return "Hola";
}
}
The assert and the verify fail. Why is that? Here is the code that is tested:
namespace ClassLibrary1
{
public class SayGoodMorning : ISayGoodMorning
{
public string GoodMorning()
{
return "Good Morning";
}
}
public interface ISayGoodMorning
{
string GoodMorning();
}
}
namespace ClassLibrary2
{
public class Greeting
{
public string SayGreeting()
{
ISayGoodMorning s = new SayGoodMorning();
return s.GoodMorning();
}
}
}
First the subject under test needs to be refactored to inject the dependency to allow a mock to be used when testing. Either via constructor or method injection. (Explicit Dependencies Principle)
This example uses constructor injection
namespace ClassLibrary2 {
public class Greeting {
private readonly ISayGoodMorning speaker;
public Greeting(ISayGoodMorning speaker) {
this.speaker = speaker;
}
public string SayGreeting() {
return speaker.GoodMorning();
}
}
}
Next the test needs to be restructured so that the Verify is done after exercising the method under test;
[TestClass]
public class UnitTest1 {
Mock<ISayGoodMorning> GoodMorningMock;
[TestInitialize]
public void init() {
//Arrange
GoodMorningMock = new Mock<ISayGoodMorning>();
GoodMorningMock.Setup(_ => _.GoodMorning()).Returns(Test());
}
[TestMethod]
public void TestMethod1() {
//Arrange cont'd
var g = new ClassLibrary2.Greeting(GoodMorningMock.Object);
var expected = "Hola";
//Act
var actual = g.SayGreeting();
//Assert
GoodMorningMock.Verify(_ => _.GoodMorning(), Times.Once());
Assert.AreEqual(expected, actual);
}
public string Test() {
return "Hola";
}
}
Here is what I am trying to do:
public class MyTests
{
private IFixture _fixture;
public MyTests()
{
_fixture = new Fixture();
_fixture.Customize<Thing>(x => x.With(y => y.UserId, 1));
}
[Theory, AutoData]
public void GetThingsByUserId_ShouldReturnThings(IEnumerable<Thing> things)
{
things.First().UserId.Should().Be(1);
}
}
I would expect the IEnumerable<Thing> things parameter passed into the test to each have a UserId of 1 but this is not what happens.
How can I make this so?
You can do that by creating a custom AutoData attribute derived-type:
internal class MyAutoDataAttribute : AutoDataAttribute
{
internal MyAutoDataAttribute()
: base(
new Fixture().Customize(
new CompositeCustomization(
new MyCustomization())))
{
}
private class MyCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customize<Thing>(x => x.With(y => y.UserId, 1));
}
}
}
You may also add other Customizations. Just keep in mind that the order matters.
Then, change the test method to use MyAutoData attribute instead, as shown below:
public class MyTests
{
[Theory, MyAutoData]
public void GetThingsByUserId_ShouldReturnThings(IEnumerable<Thing> things)
{
things.First().UserId.Should().Be(1);
}
}
I have a class that roughly looks like this:
public class ViewModel
{
public ViewModel(IWebService service)
{
this.WebService = service;
}
private IWebService WebService{get;set;}
private IEnumerable<SomeData> MyData{get;set;}
private void GetReferenceData()
{
this.WebService.BeginGetStaticReferenceData(GetReferenceDataOnComplete, null);
}
private void GetReferenceDataOnComplete(IAsyncResult result)
{
this.MyData = this.WebService.EndGetStaticReferenceData(result);
}
.
.
.
}
I want to mock my IWebService interface so that when BeginGetStaticReferenceData is called it is able to call the callback method. I'm using Moq and I can't work out how to do this. My unit test set up code looks something like:
//Arrange
var service = new Mock<IWebService>();
service.Setup(x => x.BeginGetStaticReferenceData(/*.......don't know.....*/));
service.Setup(x => x.EndGetStaticReferenceData(It.IsAny<IAsyncResult>())).Returns(new List<SomeData>{new SomeData{Name="blah"}});
var viewModel = new ViewModel(service.Object);
.
.
Here's how:
[TestMethod]
public void Test10()
{
var expectedData = new[]{new SomeData(), new SomeData()};
AsyncCallback callback = null;
IAsyncResult ar = new Mock<IAsyncResult>().Object;
var webServiceStub = new Mock<IWebService>();
webServiceStub
.Setup(ws => ws.BeginGetStaticReferenceData(It.IsAny<AsyncCallback>(), null))
.Callback((AsyncCallback cb, object state) => callback = cb)
.Returns(ar);
webServiceStub
.Setup(ws => ws.EndGetStaticReferenceData(It.IsAny<IAsyncResult>()))
.Returns(expectedData);
var sut = new ViewModel(webServiceStub.Object);
sut.DoIt();
callback(ar);
Assert.AreEqual(expectedData, sut.MyData);
}
This test assumes a slightly modified ViewModel where I added a few public members to have something against which to test:
public class ViewModel
{
public ViewModel(IWebService service)
{
this.WebService = service;
}
public IEnumerable<SomeData> MyData { get; set; }
public void DoIt()
{
this.GetReferenceData();
}
private IWebService WebService { get; set; }
private void GetReferenceData()
{
this.WebService.BeginGetStaticReferenceData(GetReferenceDataOnComplete, null);
}
private void GetReferenceDataOnComplete(IAsyncResult result)
{
this.MyData = this.WebService.EndGetStaticReferenceData(result);
}
}
This article contains a very good explanation on how to test async methods using Rhino Mocks - I'm sure it can be easily adapted to use Moq instead.