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"
}
}
Related
This question already has answers here:
How to mock a class that implements multiple interfaces
(4 answers)
Closed 2 years ago.
So I am trying to test a method call on another interface of my mock. Tried a few options and some tweaking here and there but it never registers the method as actually called. When I debug through the code/test the method is being called. The actual code is quite complex, so I created this abstract example of the problem. The class and method I want to test looks like the following:
public class ClassToTest
{
private readonly _domainRunner;
public ClassToTest(IDomainRunner domainRunner)
{
_domainRunner = domainRunner;
}
public void MethodToTest()
{
(_domainRunner as IRunner).RunAnotherTask();
}
}
The IDomainRunner and its relevant method I am trying to verify looks like this:
public class DomainRunner : IRunner, IDomainRunner
{
...
void IRunner.RunAnotherTask()
{
// irrelevant
}
}
And just for the complettness the basic test structure:
[TestClass]
public class DomainRunnerTests
{
[TestMethod]
public void TestRunSomeTask()
{
var domainRunnerMock = new Mock<IDomainRunner>();
var someClass = new ClassToTest(domainRunnerMock.Object):
// How to Assert that IRunner.RunAnotherTask was called?
}
}
I've tried to setup the Method RunAnotherTask or to directly verify it, neither was successful. This code does not really seem untestable to me or i am that wrong?
As refered by #A Friend the solution is as follows:
[TestClass]
public class DomainRunnerTests
{
[TestMethod]
public void TestRunSomeTask()
{
var domainRunnerMock = new Mock<IDomainRunner>();
var runnerMock = domainRunnerMock.As<IRunner>:
runnerMock.Setup(m => m.RunAnotherTask()).Verifiable();
var someClass = new ClassToTest(domainRunnerMock.Object):
runnerMock.Verify();
}
}
I am attempting to use NSubstitute (1.8.2), AutoFixture (3.33) and AutoFixture.AutoNSubstitute (3.33) as follows:
I have a poco which has a method and is used in my application. In order to test my application I need to mock the poco and what it returns from the method.
This is the poco (simplified from our actual model)
public class SamplePoco
{
public string SampleString { get; set; }
public virtual string GetFormattedString()
{
return this.SampleString + " formatted";
}
}
and this test
[TestMethod]
public void SampleTest()
{
var fixture = new Fixture().Customize(new AutoConfiguredNSubstituteCustomization());
var substitute = fixture.Create<SamplePoco>();
var formattedString = fixture.Create<string>();
substitute.GetFormattedString().Returns(formattedString);
// ... test goes here
}
I have determined this using code samples I have found for AutoFixture.AutoMoq as I have not been able find any specific samples for AutoFixture.AutoNSubstitute.
However, this fails with the following error:
NSubstitute.Exceptions.CouldNotSetReturnDueToNoLastCallException:
Could not find a call to return from.
What am I doing wrong?
Using NSubstitute works as expected:
[TestMethod]
public void SampleTest()
{
var fixture = new Fixture().Customize(new AutoConfiguredNSubstituteCustomization());
var substitute = Substitute.For<SamplePoco>();
var formattedString = fixture.Create<string>();
substitute.GetFormattedString().Returns(formattedString);
// ... test goes here
}
However, I want to use AutoFixture as the actual poco has many more properties and methods and the methods are more complex than this simple example.
As you wrote, SamplePoco class is a POCO, so when you call fixture.Create<SamplePoco>() in first test, you are getting a fresh new instance of SamplePoco class created by AutoFixture using reflection and invoking default constructor.
I think your first test is fine, AutoFixture create also a SampleString so, you don't need to stub GetFormattedString method.
And from testing perspective your GetFormattedString method contains behavior so you should rather test it in that way:
public void SampleTest()
{
var fixture = new Fixture().Customize(new AutoConfiguredNSubstituteCustomization());
var poco = fixture.Create<SamplePoco>();
Assert.AreEquals(string.Format("{0} {1}", poco.SampleString, "formatted"), poco.GetFormattedString());
}
AutoConfiguredNSubstituteCustomization is used if AutoFixture is asked to create instance of abstraction (either interface or abstract class) and it also setup other members of that abstraction to return values from AutoFixture
But if you want explicitly tell AutoFixture to create POCO class using NSubstitute you can use AutoDataAttribute combined with SubstituteAttribute. More information about this you can find here
EDIT
If you are using test framework that doesn't allow for using AutoData feature, you can create customization that changes AutoFixture behavior for SamplePoco class.
public class SamplePocoSubstituteCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Register(() => Substitute.For<SamplePoco>());
}
}
[TestMethod]
public void SampleTest()
{
var fixture = new Fixture().Customize(new AutoConfiguredNSubstituteCustomization())
.Customize(new SamplePocoSubstituteCustomization());
var substitute = fixture.Create<SamplePoco>();
var formattedString = fixture.Create<string>();
substitute.GetFormattedString().Returns(formattedString);
// ... test goes here
}
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();
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)
I'd like to get the currently executing NUnit test in a helper method I'm using. We're actually using NUnit for integration tests here -- not unit tests. When a test finishes, we'd like to have the test clean up some log files when it's done. Currently, I've hacked around this using the StackFrame class:
class TestHelper
{
string CurrentTestFixture;
string CurrentTest;
public TestHelper()
{
var callingFrame = new StackFrame(1);
var method = callingFrame.GetMethod();
CurrentTest = method.Name;
var type = method.DeclaringType;
CurrentTestFixture = type.Name;
}
public void HelperMethod()
{
var relativePath = Path.Combine(CurrentTestFixture, CurrentTest);
Directory.Delete(Path.Combine(Configurator.LogPath, relativePath));
}
}
[TestFixture]
class Fix
{
[Test]
public void MyTest()
{
var helper = new TestHelper();
//Do other testing stuff
helper.HelperMethod();
}
[Test]
public void MyTest2()
{
var helper = new TestHelper();
//Do some more testing stuff
helper.HelperMethod();
}
}
This works just fine, except there are cases where I'd like to make the TestHelper class part of my fixture, like this:
[TestFixture]
class Fix
{
private TestHelper helper;
[Setup]
public void Setup()
{
helper = new TestHelper();
}
[TearDown]
public void TearDown()
{
helper.HelperMethod();
}
[Test]
public void MyTest()
{
//Do other testing stuff
}
[Test]
public void MyTest2()
{
//Do some more testing stuff
}
}
I can't simply make this class into a global fixture because sometimes a single test will use it more than once, and sometimes a test need not use it at all. Sometimes a test needs to attach specific properties to the TestHelper.... things like that.
As a result, I'd like to be able to somehow get the currently executing test without having to manually repeat the name of the fixture and test in the several thousand test cases I'm looking at.
Is there a way to get such information?
NUnit 2.5.7 has added an "experimental" TestContext class. One of the properties it contains is TestName. I haven't tried it, so I don't know whether the info is available in the TearDown method.
Moving the code you have in the TestHelper constructor to the HelperMethod would do the trick for you?
class TestHelper
{
public void HelperMethod()
{
string CurrentTestFixture;
string CurrentTest;
var callingFrame = new StackFrame(1);
var method = callingFrame.GetMethod();
CurrentTest = method.Name;
var type = method.DeclaringType;
CurrentTestFixture = type.Name;
var relativePath = Path.Combine(CurrentTestFixture, CurrentTest);
Directory.Delete(Path.Combine(Configurator.LogPath, relativePath));
}
}
By the looks is that you can't because the stack frame at the point of setup and teardown does not include the test method.
As for cleaning up log files it looks like you want to have a log file per test method. Perhaps in this case it might be better to either:
Use a random id as part of the log file name which you can clean up in the teardown of the helper class. If however the name of the test method is required to be part of the log file you could do..
You can implement IDisposable todo the cleanup
[Test]
public void MyTest()
{
using(new TestHelper())
{
... test goes here ...
}
}
Or use PostSharp to weave the above code as part of an attribute on your test method.
[Test, TestHelper]
public void MyTest()
{
...
}
[EDIT]
fixed formatting. Added IDisposable