I want to test a method with no return, which only runs code if a passed in bool is set to true.
I'd like to test that when the bool is false, no code is called. I expect, this is maybe a case of refactoring to make my code more testable.
Code speaks a thousand words, so here's my method (constructor and dependencies left out for brevity):
...
public void Handle(Notification notification)
{
if (notification.IsRestarting)
{
var installedVersion = _versionService.GetValue("Version");
var packageVersion = "1.0.0";
if (installedVersion.IsNullOrWhiteSpace())
{
_service.Initialise();
}
_versionService.SetValue("Version", packageVersion);
}
}
...
I'm using Moq for mocking.
The _versionService actually sets the value in a SQL database table. This is a third-party service, though it is mockable.
So, if isRestarting is false, the method should do nothing. How do I test this, or make my code more testable?
You can check that your services were never called. Assuming that _versionService is a Mock<ISomeVersionService>. Some rough code -
[Test]
public void MyTest()
{
//call the method
Handle(new Notification { IsRestarting = false });
//verify nothing happened
_versionService.Verify(x => x.GetValue(It.IsAny<string>(), Times.Never))
//handle _service similarly
}
Related
Problem
I want to unit test a method in my repository class that checks if a record should be updated or created new.
How do I test the main function without actually having the unit test attempt to insert or query the db?
Code
I have the following repository class:
public class WidgetRepository()
{
public bool InsertOrUpdateWidget(Widget widgetToEval)
{
var retval = false;
var existingRecord = FindExistingWidget(widgetToEval);
if (existingRecord == null)
{
retval = InsertNewWidget(widgetToEval);
}
else
{
retval = UpdateExistingWidget(widgetToEval, existingRecord);
}
return retval;
}
Unit Test
[Fact]
public void Insert_New_Widget()
{
var repo = GetEmptyRepository();
var newWidget = new Widget()
{
ID = 1,
Name= "test",
Description= "Test widget",
};
var result = repo.InsertOrUpdateWidget(newWidget);
Assert.True(result);
}
private IWidgetRepository GetEmptyRepository()
{
var repo = new Mock<IWidgetRepository >();
repo.Setup(s => s.FindExistingWidget(It.IsAny<Widget>())).Returns((Widget)null);
repo.Setup(s => s.InsertNewWidget(It.IsAny<Widget>())).Returns(true);
return repo.Object;
}
In the unit test, I'm trying to mock the FindExistingWidget method and have it return a null object. I've also mocked the insert function and have it return a true.
When I run this test, instead of returning a true, it returns false.
Edit 1
So I understand that I shouldn't mock the repo... I should just create an object of this type because I should only mock things my code needs / dependencies.
But I guess the question is then how do i prevent the code from actually attempting to connect to the db when it runs the FindExistingWidget() method or the actual InsertNewWidget method?
I just want to unit the test the logic inside the InsertorUpdate method to make sure its doing the right thing
When you want to test your repository you don't test the interface. You mock your repo when you want you want to test somehting using it. It's 'unit' test so you should test every method while it's sepereated from the others.
You should be testing WidgetRepository and not IWidgetRepository.
As the previous answers states, you are not Mocking the call to InsertOrUpdateWidget(), so its returning false (it's not even calling the code in the concrete class)
If you are going to mock your repository and you just want it to return true, then do this;
private IWidgetRepository GetEmptyRepository()
{
var repo = new Mock<IWidgetRepository >();
repo.Setup(s => s.InsertOrUpdateWidget(It.IsAny<Widget>())).Returns(true);
return repo.Object;
}
You can't mock just a portion of the WidgetRepository class. In the instance you are using above is your mock, and based on your setup above, you did not implement the function you are calling (InsertOrUpdateWidget) with repo.Setup. Since it returns a boolean, it will default to the value false. This function may be implemented in your concrete implementation of IWidgetRepository, but it isn't in your mock. The return statement return repo.Object; is not of WidgetRepository, but of a mocked version of IWidgetRepository. These are two different implementations, and only one of them implements InsertOrUpdateWidget. It isn't the one you are testing.
I'm trying to use FakeItEasy (version 4.9.1) to create unit tests for some legacy code. I've created two unit tests, one of which works just as expected, and one very similar which doesn't work despite lots of trial and error.
Here's an excerpt from the method that seems impossible to test:
public class PosMessageProcessor : IPosMessageProcessor
{
public void Execute()
{
PurchaseOrderRepository repo = new PurchaseOrderRepository();
...
try
{
m_PurchaseOrder = GetOrderForProcessing(repo);
...
And here's my test:
[TestMethod]
[TestCategory("POS")]
public void ExecuteTest()
{
// Arrange
PurchaseOrder purchaseOrder = GetPurchaseOrder();
IPosMessageProcessor fakePosMessageProcessor = A.Fake<IPosMessageProcessor>();
A.CallTo(() => fakePosMessageProcessor.GetOrderForProcessing(A<IPurchaseOrderRepository>.Ignored)).Returns(purchaseOrder);
// Act
_posMessageProcessor.Execute();
// Assert
A.CallTo(() => fakePosMessageProcessor.GetOrderForProcessing(A<IPurchaseOrderRepository>.Ignored)).MustHaveHappened();
}
The _posMessageProcessor variable is an instance of the PosMessageProcessor class. I want to catch the call to the GetOrderForProcessing() method (within the Execute() method) and make it return my hard-coded purchaseOrder object. But I get another return value (null) instead. Why?
The unit test that works tests the GetOrderForProcessing() method:
[TestMethod]
[TestCategory("POS")]
public void GetOrderForProcessingTest()
{
// Arrange
PurchaseOrder purchaseOrder = GetPurchaseOrder();
IPurchaseOrderRepository fakePurchaseOrderRepository = A.Fake<IPurchaseOrderRepository>();
A.CallTo(() => fakePurchaseOrderRepository.GetPurchaseOrderByOrderTrackingNumber(A<string>.Ignored)).Returns(purchaseOrder);
// Act
PurchaseOrder result = _posMessageProcessor.GetOrderForProcessing(fakePurchaseOrderRepository);
// Assert
A.CallTo(() => fakePurchaseOrderRepository.GetPurchaseOrderByOrderTrackingNumber(A<string>.Ignored)).MustHaveHappened();
Assert.IsNotNull(result);
}
In this case, the call to GetPurchaseOrderByOrderTrackingNumber() returns my hard-coded object as expected. The two tests are virtually the same, except that the GetOrderForProcessing() method takes a parameter while Execute() does not.
ExecuteTest is failing because you configure a fake IPosMessageProcessor and then call Execute on a real PosMessageProcessor, _posMessageProcessor. _posMessageProcessor, being an actual PosMessageProcessor, executes its regular code path, calling the actual Execute, which will call the actual GetOrderForProcessing.
(Note that you can actually delete the fakePosMessageProcessor variable and all references to it from your test, and the behaviour will be the same.)
I do not recommend this kind of testing, but in order to fake GetOrderForProcessing and still test the actual Execute code, you would have to write a test like
public void NewExecuteTest()
{
// Arrange
PurchaseOrder purchaseOrder = GetPurchaseOrder();
// Get a fake PosMessageProcessor that falls back to original behaviour for all calls.
IPosMessageProcessor fakePosMessageProcessor = A.Fake<PosMessageProcessor>(options => options.CallsBaseMethods());
// Now fake out the GetOrderForProcessing call so we can test Execute.
A.CallTo(() => fakePosMessageProcessor.GetOrderForProcessing(A<IPurchaseOrderRepository>.Ignored)).Returns(purchaseOrder);
// Act
fakePosMessageProcessor.Execute();
// Assert
A.CallTo(() => fakePosMessageProcessor.GetOrderForProcessing(A<IPurchaseOrderRepository>.Ignored)).MustHaveHappened();
}
I have a class that gets knockout messages using the method below:
public IEnumerable<Message> GetKnockoutMessages(Data data)
{
if(data.Messages != null)
{
return data.Messages.Where(m => m.UnderWritingRuleId != null);
}
else
{
return new List<Message>();
}
}
So far, i have a unit test that only partially covers the unit test which is below.
[TestMethod]
public void TestGetKnockoutMessages()
{
KnockoutUtility knockUtility = new KnockoutUtility();
IEnumerable<Message> messages = knockUtility.GetKnockoutMessages(MockData.Object);
Assert.IsNotNull(messages);
}
This covers everything but return data.Messages.Where(m => m.UnderWritingRuleId != null);
I was wondering how I would unit test this method to get 100% coverage.
Any help would be appreciated. Thanks
This unit test doesn't cover everything because you are not verifying all cases. You have to test two logics:
if/else logic
Where(m => m.UnderWritingRuleId != null) logic
Based on this assumption you have to create cases which proof following:
If data.Messages are null then you have to verify that method returns new instance of List<Message>() because you specified in code like that.
Next case will be to verify that method returns empty IEnumerable<Message> if data.Messages are empty (which means this condition data.Messages.Count() == 0).
Next case will be to verify that method returns exact messages which satisfied your condition: Where(m => m.UnderWritingRuleId != null). In other words only messages which have populated UnderWritingRuleId.
To achieve what I mentioned you have to create Data objects which satisfied this cases. I don't know what is MockData.Object but I hope that you included you arrangement there.
Each case should be in separate test method like in following:
[TestMethod]
public void TestGetKnockoutMessages_Case1()
{
// Arrange
// Action
// Assert
}
[TestMethod]
public void TestGetKnockoutMessages_Case2()
{
// Arrange
// Action
// Assert
}
[TestMethod]
public void TestGetKnockoutMessages_Case3()
{
// Arrange
// Action
// Assert
}
Arrange is place where you configuring your mock-ups. Action is place where you executing method which you want to test and Assert is place where you doing assertion.
I'm using FakeItEasy to do some testing, but I have run into a problem.
When testing that the expected data is sent to a faked service, I would like to be able to see the error data as well.
Right now I only see that the call never happened.
Maybe I'm setting it up all wrong, but then I'd like some hints on how to correct it. :)
My case is:
A call to the same service twice, with different values.
I want separate tests to verify each call.
If any of the parameters, doesn't have the expected value, I would like to get an error message stating that. Similar to when you do an Assert.AreEqual().
Right now I only get "Call did not happen", which is totally understandable, because I realise that is what I'm testing. But I would like to be able to verify that a specific call has only been made once, and if it did not happen I would like to see which values were used to not make it happen.
I used this solution: http://thorarin.net/blog/post/2014/09/18/capturing-method-arguments-on-your-fakes-using-fakeiteasy.aspx
when I only had one call, but with two calls it doesn't work.
[TestFixture]
public class TestClass
{
[Test]
public void TestOne()
{
// Arrange
var fake = A.Fake<IBarservice>();
var a = new Foo(fake);
// Act
a.DoStuff(1);
//Assert
A.CallTo(() => fake.DoOtherStuff(A<int>.That.Matches(x => x == 2))).MustHaveHappened(Repeated.Exactly.Once);
}
[Test]
public void TestTwo()
{
// Arrange
var fake = A.Fake<IBarservice>();
var a = new Foo(fake);
// Act
a.DoStuff(1);
//Assert
A.CallTo(() => fake.DoOtherStuff(A<int>.That.Matches(x => x == 3))).MustHaveHappened(Repeated.Exactly.Once);
}
}
public class Foo
{
private readonly IBarservice _barservice;
public Foo(IBarservice barservice)
{
_barservice = barservice;
}
public void DoStuff(int someInt)
{
someInt++;
_barservice.DoOtherStuff(someInt);
// I should have increased someInt here again, but this is a bug that my tests catches
_barservice.DoOtherStuff(someInt);
}
}
public interface IBarservice
{
void DoOtherStuff(int someInt);
}
Markus, I had a comment that I've redacted, since I made an error.
You say you only get "Call did not happen" and
… I would like to be able to verify that a specific call has only been made once, and if it did not happen I would like to see which values were used to not make it happen.
I fear I don't understand what information you were hoping for, since when I run TestOne, I get
FakeItEasy.ExpectationException
Assertion failed for the following call:
FakeItEasyQuestionsVS2015.IBarservice.DoOtherStuff(<x => (x == 2)>)
Expected to find it exactly once but found it #2 times among the calls:
1: FakeItEasyQuestionsVS2015.IBarservice.DoOtherStuff(someInt: 2) repeated 2 times
...
This says that the call DoOtherStuff was made twice, with someInt passed in as the value 2 each time.
I want to ignore certain tests based on data I pulled from a configuration file during the TestFixtureSetUp. Is there a way to ignore running a test based on parameters?
[TestFixture]
public class MessagesTests
{
private bool isPaidAccount;
[TestFixtureSetUp]
public void Init () {
isPaidAccount = ConfigurationManager.AppSettings["IsPaidAccount"] == "True";
}
[Test]
//this test should run only if `isPaidAccount` is true
public void Message_Without_Template_Is_Sent()
{
//this tests an actual web api call.
}
}
If account we are testing with is a paid account, the test should run fine, if not, the method will throw an exception.
Would there be an extension of the attribute [Ignore(ReallyIgnore = isPaidAccount )]? Or should I write this inside the method and run 2 separate test cases for eg.
public void Message_Without_Template_Is_Sent()
{
if(isPaidAccount)
{
//test for return value here
}
else
{
//test for exception here
}
}
You can use Assert.Ignore() like Matthew states. You could also use Assert.Inconclusive() if you want to categorize the result differently.
This Question/Answer is slightly similar: Programmatically skip an nunit test