I am fairly new to unit testing in C# and learning to use Moq. Below is the class that I am trying to test.
class MyClass
{
SomeClass someClass;
public MyClass(SomeClass someClass)
{
this.someClass = someClass;
}
public void MyMethod(string method)
{
method = "test"
someClass.DoSomething(method);
}
}
class Someclass
{
public DoSomething(string method)
{
// do something...
}
}
Below is my TestClass:
class MyClassTest
{
[TestMethod()]
public void MyMethodTest()
{
string action="test";
Mock<SomeClass> mockSomeClass = new Mock<SomeClass>();
mockSomeClass.SetUp(a => a.DoSomething(action));
MyClass myClass = new MyClass(mockSomeClass.Object);
myClass.MyMethod(action);
mockSomeClass.Verify(v => v.DoSomething(It.IsAny<string>()));
}
}
I get the following exception:
Expected invocation on the mock at least once, but was never performed
No setups configured.
No invocations performed..
I just want to verify if the method "MyMethod" is being called or not. Am I missing something?
You're checking the wrong method. Moq requires that you Setup (and then optionally Verify) the method in the dependency class.
You should be doing something more like this:
class MyClassTest
{
[TestMethod]
public void MyMethodTest()
{
string action = "test";
Mock<SomeClass> mockSomeClass = new Mock<SomeClass>();
mockSomeClass.Setup(mock => mock.DoSomething());
MyClass myClass = new MyClass(mockSomeClass.Object);
myClass.MyMethod(action);
// Explicitly verify each expectation...
mockSomeClass.Verify(mock => mock.DoSomething(), Times.Once());
// ...or verify everything.
// mockSomeClass.VerifyAll();
}
}
In other words, you are verifying that calling MyClass#MyMethod, your class will definitely call SomeClass#DoSomething once in that process. Note that you don't need the Times argument; I was just demonstrating its value.
Related
I moved the most frequently created mocks into extensions and helper classes to be able to reuse them in several tests. I was very surprised when it turned out that they are appently context dependent and don't work when sitting elsewhere.
This code demonstrates the issue:
void Main()
{
// Does not get the mock user.
var db = MockFactory.MockUserDatabase();
db.GetUsersAsync().GetAwaiter().GetResult().Dump(); // <-- null
// This works and gets the mock user.
var mock = Mock.Create<IUserDatabase>();
mock
.Arrange(x => x.GetUsersAsync())
.Returns(Task.FromResult(new[] { new User { Name = "John" } }));
mock.GetUsersAsync().GetAwaiter().GetResult().Dump(); // <-- mock user
}
static class MockFactory
{
public static IUserDatabase MockUserDatabase()
{
var mock = Mock.Create<IUserDatabase>();
mock
.Arrange(x => x.GetUsersAsync())
.ReturnsTask(new[] { new User { Name = "John" } });
return mock;
}
}
public static class JustMockHelpers
{
public static IAssertable ReturnsTask<TReturn>(this IAssertable assertable, TReturn value)
{
return assertable.Returns(Task.FromResult<TReturn>(value));
}
}
public interface IUserDatabase
{
Task<User[]> GetUsersAsync();
}
public class User
{
public string Name { get; set; }
}
Is there any way I can make the JustMock code encapsulated in other classes work too?
The problem here is you are using a Static MockFactory and it works when you use it directly not statically. Why Would use a static class if you are still initiating the test data each time and each time you recreate the mock? Either try to have a base testing class with this method and call it base.YourInitialiseMethod() or something like TestFixtures. If you look at documentation of JustMock they always do create inside each test case individually.
I have found a trick. You can pull it to the same static context with a Func. ReturnsTask still won't cooperate but at least the general arrangement does.
static class MockFactory
{
public static Func<IUserDatabase> MockUserDatabase
{
get
{
return () =>
{
var mock = Mock.Create<IUserDatabase>();
mock
.Arrange(x => x.GetUsersAsync())
.Returns(new[] { new User { Name = "John" } }.ToTask());
return mock;
};
}
}
}
I turned the other extension around and made it:
public static Task<T> ToTask<T>(this T obj) => Task.FromResult(obj);
Then I just call:
.Returns(new[] { new User { Name = "John" } }.ToTask())
How can I mock the CasOperations.GetImpairedNodesFromCASpectrumAsync() method so that it returns the mocked value? Currently, I am getting an exception (shown below the code examples).
I have the following setup:
Class and property to be mocked:
public class BranchCircuitStatusScheduleEntry : NWatchCustomScheduleEntryBase, INWatchCustomScheduleEntry
{
public BranchCircuitStatusScheduleEntry(INWatchSchedulerApplication application)
: base(application, DevOpsScheduleFrequency.Minute, 15, 0, DevOpsScheduleFlags.Always)
{
// Some initialization for below properties
CasOperations = new CasOperations(cas, EntityService, IsBranchesOnly);
}
public CasOperations CasOperations { get; private set; }
}
public class CasOperations
{
public CasOperations(CasApi casApi, BranchCircuitEntityService entityService, bool isBranchesOnly)
{
CAS = casApi;
this.entityService = entityService;
this.isBranchesOnly = isBranchesOnly;
}
}
Test that tries to perform mocking:
[TestMethod]
public void DownNodeRediscoveredInSpectrum()
{
var mock = new Mock<BranchCircuitStatusScheduleEntry>(_application);
mock.CallBase = true;
// Spectrum's artificial response with a model with the same name, but a "new" model handle
var mockedNewlyImpairedNodes = new NetworkDeviceNodeStatus[]
{
new NetworkDeviceNodeStatus
{
// Not important
}
};
mock.Setup(x =>
x.CasOperations.GetImpairedNodesFromCASpectrumAsync()).ReturnsAsync(mockedNewlyImpairedNodes);
}
Exception thrown in the test:
An exception of type
'Castle.DynamicProxy.InvalidProxyConstructorArgumentsException'
occurred in Moq.dll but was not handled in user code Additional
information: Can not instantiate proxy of class:
NWatch.NetworkCircuits.CasOperations. Could not find a parameterless
constructor.
Allow me to give it a try:
In the setup of the mock you are not trying to mock the behaviour of the BranchCircuitStatusScheduleEntry, but the behaviour of the CasOperations class. So you really need a Mock<CasOperations> object. Or even better, a Mock<ICasOperations> as #Jonesopolis said in his comment.
Besides, in the BranchCircuitStatusScheduleEntry constructor you are initializing both the instance of that class and the instance of CasOperations. It would be better if you initialize the instance of CasOperations outside the BranchCircuitStatusScheduleEntry constructor and pass it as a parameter.
So it would be like this:
public class BranchCircuitStatusScheduleEntry : NWatchCustomScheduleEntryBase, INWatchCustomScheduleEntry
{
public BranchCircuitStatusScheduleEntry(INWatchSchedulerApplication application, ICasOperations casOperations)
: base(application, DevOpsScheduleFrequency.Minute, 15, 0, DevOpsScheduleFlags.Always)
{
CasOperations = casoperations;
}
public CasOperations CasOperations { get; private set; }
}
Finally, you create your mock, set it up and pass it as a parameter to the BranchCircuitStatusScheduleEntry constructor:
var casMock = new Mock<ICasOperations>();
casMock.Setup(x => x.GetImpairedNodesFromCASpectrumAsync()).ReturnsAsync(mockedNewlyImpairedNodes);
var mock = new Mock<BranchCircuitStatusScheduleEntry>(_application, casMock.Object);
mock.CallBase = true;
Note that maybe this last instance of BranchCircuitStatusScheduleEntry should not be a mock, but a real object (the instance under test).
I have a helper class which inherits from an Interface and has three dependencies.
public class StudentHelper : IStudentHelper
{
private readonly IUpdateStudentManager _updateStudentManager;
private readonly ISchedulerHelper _schedulerHelper;
public StudentHelper(
IUpdateStudentManager updateStudentManager,
ISchedulerHelper schedulerHelper)
{
_updateStudentManager = updateStudentManager;
_schedulerHelper = schedulerHelper;
}
// Rest of the class not shown here for brevity.
}
To test this I wrote a test class like so:
[TestClass]
public class StudentHelperTests
{
private Mock<StudentHelper> _studentHelperMock;
private Mock<IUpdateStudentManager> _updateStudentManagerMock;
private Mock<ISchedulerHelper> _schedulerHelperMock;
[TestInitialize]
public void Setup()
{
_updateStudentManagerMock = new Mock<IUpdateStudentManager>();
_schedulerHelperMock = new Mock<ISchedulerHelper>();
_studentHelperMock = new Mock<StudentHelper>(_updateStudentManagerMock.Object,
_schedulerHelperMock.Object);
}
[TestMethod]
public void Calling_GetEndDate_Returns_A_FutureDate()
{
_productRulesHelper.Setup(x=>x.GetEndDate(DateTime.UtcNow.ToShortDateString(),1)).Returns(DateTime.UtcNow.AddYears(1).ToString("MM/dd/yyyy"));
_productRulesHelper.VerifyAll();
}
}
The method to test returns this error:
Test method StudentHelperTests.Calling_GetEndDate_Returns_A_FutureDate
threw exception:
System.NotSupportedException: Invalid setup on a non-virtual
(overridable in VB) member: x =>
x.GetEndDate(DateTime.UtcNow.ToShortDateString(), 1)
The GetEndDate method just takes in a date as string, adds a year and returns the resulting date as string.
I think the way StudentHelperMock is initialized is not correct!!!
Can someone please guide me on this?
Thanks in advance.
You're not supposed to create a mock for the instance you're trying to test - you're supposed to create a mock for its dependencies.
The purpose of mocking is to isolate the system under test (StudentHelper) from its dependencies (IUpdateStudentManager, ISchedulerHelper) by replacing them with test doubles (e.g. mocks).
Here's what your test case should look like:
[TestMethod]
public void Calling_GetEndDate_Returns_A_FutureDate()
{
// Arrange
var helper = new StudentHelper(_updateStudentManagerMock.Object, _schedulerHelperMock.Object);
var now = DateTime.UtcNow;
// Act
var result = x.GetEndDate(now.ToShortDateString(),1);
// Assert
Assert.Equal(now.AddYears(1).ToString("MM/dd/yyyy"), result);
}
On a side note: I would also advise against the usage of global test setups. See: Why you should not use SetUp and TearDown in NUnit.
Related reading:
The Little Mocker by Uncle Bob
When to Mock by Uncle Bob
Try something like this:
[TestClass]
public class StudentHelperTests
{
private StudentHelper _objectToTest;
private Mock<IUpdateStudentManager> _updateStudentManagerMock;
private Mock<ISchedulerHelper> _schedulerHelperMock;
[TestInitialize]
public void Setup()
{
_updateStudentManagerMock = new Mock<IUpdateStudentManager>();
_schedulerHelperMock = new Mock<ISchedulerHelper>();
_studentHelperMock = StudentHelper(_updateStudentManagerMock.Object,
_schedulerHelperMock.Object);
}
[TestMethod]
public void Calling_GetEndDate_Returns_A_FutureDate()
{
// The method name says:
var retrievedDate = _objectToTest.GetEndDate();
Assert()//... And you should verify than the retrieved date is "a future date"
}
}
I'm working with the FakeItEasy library to create fakes for my unit tests.
I have a ClassUnderTest on which I want to test the method MethodToTest(Data dataObject). This method is calling a method of an interface which I want to fake:
public interface IFoo
{
void Execute(Action<IDataAccess> action);
}
public class ClassUnderTest
{
private IFoo _foo;
public ClassUnderTest(IFoo foo)
{
_foo = foo;
}
public void MethodToTest(Data dataObject)
{
_foo.Execute(dataAccess => dataAccess.Update(dataObject));
}
}
public interface IDataAccess
{
void Update(Data data);
}
public class Data
{
public int Property { get; set; }
}
In my unit tests I want to check if the test method calls the interface correctly (with the correct property value):
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var foo = A.Fake<IFoo>(x => x.Strict());
A.CallTo(() => foo.Execute(dataAccess => dataAccess.Update(A<Data>.That.Matches(d => d.Property == 20))));
var cut = new ClassUnderTest(foo);
cut.MethodToTest(new Data { Property = 20 });
}
}
But something is configured wrong in this test. I get the exception:
Test method TestProject1.UnitTest1.TestMethod1 threw exception:
FakeItEasy.ExpectationException: Call to non configured method "Execute" of strict fake.
Does somebody have an idea of how I have to configure the CallTo() statement correctly?
The updated example really helps, #rhe1980.
First some notes about the test you supplied:
the A.CallTo method doesn't do anything - it's not setting up behaviour (with a .Invokes or a .Returns or even a .DoesNothing) or verifying that the method has been called (for example with .MustHaveHappened).
Comparing Actions appears to be tough. I did find some advice over at Compare Delegates Action<T>, but if it were me, I'd take a slightly different tack.
Instead of attempting to compare the Action delegate to a reference model, I figured I could emulate this by capturing the action supplied to Execute and then running it on an IDataAccess and see what the action does. Fortunately, we have FakeItEasy to help with that!
I had success with this test:
[TestMethod]
public void TestMethod1()
{
// Arrange
var foo = A.Fake<IFoo>(x => x.Strict());
var fakeDataAccess = A.Fake<IDataAccess>();
A.CallTo(() => foo.Execute(A<Action<IDataAccess>>.Ignored))
.Invokes((Action<IDataAccess> action)=>action(fakeDataAccess));
var cut = new ClassUnderTest(foo);
// Act
cut.MethodToTest(new Data { Property = 20 });
// Assert
A.CallTo(() => fakeDataAccess.Update(A<Data>.That.Matches(d => d.Property == 20)))
.MustHaveHappened();
}
I hope it helps.
If I understood your intentions correctly, you need to use something as follows:
A.CallTo(() => foo.Execute(A<Action<IDataAccess>>.Ignored).MustHaveHappened();
Here is an example where I am testing the line if (true). But although the condition is obviously true, Moq tells me the method was never called.
public class test
{
public virtual void start()
{
if (true)
called();
}
public virtual void called()
{
}
}
[Test]
public void QuickTest()
{
var mock = new Mock<test>();
mock.Object.start();
mock.Verify(t => t.start(), "this works");
mock.Verify(t => t.called(), "crash here: why not called?");
}
How do I test that the method call to called() has happened?
I thought Moq was the solution, but from the comments it looks like it isn't so I've made another example without any reference to Moq:
public class test
{
public bool condition = true;
public test(bool cond)
{
condition = cond;
}
public virtual string start()
{
var str = "somestuff";
if (condition)
str += called();
str += "something more";
return str;
}
public virtual string called()
{
return "something more";
}
}
[Test]
public void ConditionTrue_CallsCalled()
{
var t = new test(true);
t.start();
//syntax? t.HasCalled("called");
Assert.IsTrue(result.Contains("something more"));
}
[Test]
public void ConditionFalse_NoCall()
{
var t = new test(false);
t.start();
//syntax? t.HasNotCalled("called");
// Can't check this way because something more is already being added
Assert.IsFalse(result.Contains("something more"));
}
Is it possible to do this? Is it worthwhile?
Regarding the first piece of code:
mock is a mock object. That means all the methods are overridden and do nothing. So it's entirely normal that calling mock.start() doesn't do anything and called() is never called.
If you want to mock just called() and use the real implementation of start(), you need to do partial mocking.
But I would advise against that, I would even advise against trying to test just this class. You will couple your test code too tightly to your implementation code. Think about doing TDD: ask yourself what feature of your application breaks if that if test is not there. Write a test against that feature, which should fail. Then write the if test to fix the test.