I have a class:
public class BankingTransfer : IBankingTransfer
{
public decimal GetTrustAccountBalance(string Id, string Pin)
{
throw new NotImplementedException();
}
Now I want to do a xunit test on it. But not sure how to test a dummy return value?
My code:
public class GetTrustAccountBalanceUnitTest
{
[Theory]
[InlineData("1234")]
[InlineData("1234")]
public void GetTrustAccountBalance_Should_Return_A_Value(string expectedId,string expectedPin)
{
// ARRANGE
var bankingTransferMock =new Mock<IBankingTransfer>();
// ACT
bankingTransferMock.Setup(x=>x.GetTrustAccountBalance(expectedId,expectedPin)).Returns()
// ASSURE
}
}
Just put a value inside the returns value like this:
bankingTransferMock.Setup(x=>x.GetTrustAccountBalance(expectedId,expectedPin)).Returns(1);
However, I think that you have misunderstood how to test the class that you have displayed. You shouldn't mock the class that you are trying to test. Going by the test name you probably want something more along these lines where you are just calling the method and seeing what is returned.
var bankingTransfer = new BankingTransfer();
Assert.True(bankingTransfer.GetTrustAccountBalance("", "") > 0);
Related
Could someone tell me i this is a correct unit test for FillUpContainer()?
namespace CoffeeMaker
{
[TestClass()]
public class WaterContainer
{
//private WaterContainer WaterC;
WaterContainer WaterC = new WaterContainer(0);
int level = WaterC.Level;
[TestMethod()]
public void FillUpWaterTest()
{
if (WaterC.Level == 0)
{
bool result;
result = WaterC.FillUpWater();
}
level.Equals(5);
}
}
}
No, it's not. level.Equals(5) is not an assertion, it's just an expression, the result of which you throw away by not assigning to anything.
A better test might look something like this:
[TestClass()]
public class WaterContainer
{
[TestMethod()]
public void WhenWaterContainerIsEmpty_FillingItUp_CausesCorrectWaterLevel()
{
// arrange
WaterContainer water = new WaterContainer(0);
// act
water.FillUpWater();
// assert
Assert.AreEqual(5, water.Level);
}
}
Notice the method name describes what's being tested, and the test is self-contained (all local variables).
The Assert statement will cause the test to actually fail if the water level is not correct.
Instead of this:
level.Equals(5);
I believe you want this:
Assert.AreEqual(5, WaterC.Level);
This will cause the unit test to fail if WaterC.Level != 5.
I have been using RhinoAutoMocker for unit testing, and it works very well in almost all cases. I'm currently having trouble figuring out is how to use it when the Class Under Test has primitive constructor arguments.
Let's say I have two classes defined as such:
public class AddAnswerValidator : BaseValidator
{
public AddAnswerValidator(Answer answerToAdd,
IAnswerRepository answerRepository)
{
...some code
}
public override bool Validates()
{
...some code
}
}
public class RemoveAnswerValidator : BaseValidator
{
public RemoveAnswerValidator(int answerIDToRemove,
IAnswerRepository answerRepository)
{
...some code
}
public override bool Validates()
{
...some code
}
}
An example test for each are as follows:
[Test]
public void AddAnswerValidatorTests_Validates_ValidInput_ReturnsTrue()
{
var autoMocker = new RhinoAutoMocker<AddAnswerValidator>();
var fakeAnswer = new Answer();
autoMocker.Inject<Answer>(fakeAnswer);
var result = autoMocker.ClassUnderTest.Validates();
Assert.IsTrue(result);
}
[Test]
public void RemoveAnswerValidatorTests_Validates_ValidInput_ReturnsTrue()
{
var autoMocker = new RhinoAutoMocker<RemoveAnswerValidator>();
var fakeAnswerID = 1;
autoMocker.Inject<int>(fakeAnswerID);
var result = autoMocker.ClassUnderTest.Validates();
Assert.IsTrue(result);
}
The first test (for AddAnswerValidator) works fine. The second test (for RemoveAnswerValidator) fails with a StructureMap 202 Error "No default instance defined for plugin family RemoveAnswerValidator" error. I'm working under the assumption that the second test is failing because StructureMap isn't resolving the integer constructor argument.
I've read through this post regarding RhinoAutoMocker Injection for collections and I've been tracing through the source code on GitHub, but I don't understand why the primitive value isn't being injected.
I've even tried substituting some of the overloaded Inject methods available on the container object such as:
autoMocker.Inject<int>(fakeAnswerID);
with
autoMocker.Container.Inject<int>("answerIDToRemove", fakeAnswerID);
but using the name of the constructor argument doesn't produce any different results.
--
In the long run, this isn't a huge problem since I can always just create an instance of the Class Under Test and create my own mocks, it would just be nice to be able to use a consistent methodology across all of my tests.
I know, it's a little bit too late, but i had the same problem and managed to solve it with integer parameter:
var autoMocker = new RhinoAutoMocker<RemoveAnswerValidator>();
automocker.Container.Configure(c=>
c.For<RemoveAnswerValidator>()
.Use<RemoveAnswerValidator>()
.Ctor<int>()
.Is(1));
While I never did find a way to inject a primitive using AutoMocker, I ended up working around the problem by creating a parameter object and injecting that instead.
The parameter object then includes the necessary primitives as a properties, in addition to the other (former) parameters. The example above would be changed to:
public class RemoveAnswerValidator : BaseValidator
{
public RemoveAnswerValidator(RemoveAnswerValidatorParameters parms)
{
...some code
}
public override bool Validates()
{
...some code
}
}
public class RemoveAnswerValidatorParameters
{
public int AnswerID { get; set; }
public IAnswerRepository AnswerRepository { get; set; }
}
(Then in the test class)
[Test]
public void RemoveAnswerValidatorTests_Validates_ValidInput_ReturnsTrue()
{
var autoMocker = new RhinoAutoMocker<RemoveAnswerValidator>();
var fakeAnswerParameters = new FakeAnswerParameters()
{
AnswerID = 1,
AnswerRepository = autoMocker.Get<IAnswerRepository>()
};
autoMocker.Inject<RemoveAnswerValidatorParameters>(fakeAnswer);
var result = autoMocker.ClassUnderTest.Validates();
Assert.IsTrue(result);
}
I have the following simple class Data annotation to control the area of phone number:
public class PhoneAreaAttribute : ValidationAttribute, IClientValidatable
{
public const string ValidInitNumber = "0";
public const int MinLen = 2;
public const int MaxLen = 4;
public override bool IsValid(object value)
{
var area = (string)value;
if (string.IsNullOrWhiteSpace(area))
{
return true;
}
if (area.StartsWith(PhoneAreaAttribute.ValidInitNumber))
{
return false;
}
if (!Regex.IsMatch(area, #"^[\d]+$"))
{
return false;
}
if (!area.LengthBetween(PhoneAreaAttribute.MinLen, PhoneAreaAttribute.MaxLen))
{
return false;
}
return true;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
ValidationType = "phoneArea",
};
yield return rule;
}
}
I do not know how it would be a correct unit test for this class.
thanks.
Okay, basically testing an attribute is the same as testing any regular class. I took your class and reduced it a little bit so I could run it (you created some extension methods, which I didn't want to recreate). Below you find this class definition.
public class PhoneAreaAttribute : ValidationAttribute
{
public const string ValidInitNumber = "0";
public override bool IsValid(object value)
{
var area = (string)value;
if (string.IsNullOrEmpty(area))
{
return true;
}
if (area.StartsWith(PhoneAreaAttribute.ValidInitNumber))
{
return false;
}
return true;
}
}
Note beforehand: some of my naming conventions for unit tests might differ from the ones you use (there are a few out there).
Now we will create a Unit Test. I understood that you already have a Test Project, if you don't have one, just create one. In this test project, you will create a new unit test (Basic Unit Test), let's name it PhoneAreaAttributeTest.
As good practice, I create a test initialiser to create all shared "resources", in this case a new instance of the PhoneAreaAttribute class. Yes, you can just create an instance, like you are used to with "regular" classes (as a matter of fact, there isn't that much difference between "regular" classes and your attribute class).
Now we are ready to start writing the tests for the methods. Basically you will want to handle all possible scenarios. I will show you here two scenarios that are possible in my (reduced) IsValid method. First I will see whether the given object parameter can be cased to a string (this is a first scenario / TestMethod). Second I will see whether the path of "IsNullOrEmpty" is properly handled (this is a second scenario / TestMethod).
As you can see, it is just a regular unit test. These are just the very basics. If you still have questions, I would like to also suggest you to read some tutorials.
Here is the PhoneAreaAttributeTest test class:
[TestClass]
public class PhoneAreaAttributeTest
{
public PhoneAreaAttribute PhoneAreaAttribute { get; set; }
[TestInitialize]
public void PhoneAreaAttributeTest_TestInitialise()
{
PhoneAreaAttribute = new PhoneAreaAttribute();
}
[TestMethod]
[ExpectedException(typeof(InvalidCastException))]
public void PhoneAreaAttributeTest_IsValid_ThrowsInvalidCastException()
{
object objectToTest = new object();
PhoneAreaAttribute.IsValid(objectToTest);
}
[TestMethod]
public void PhoneAreaAttributeTest_IsValid_NullOrEmpty_True()
{
string nullToTest = null;
string emptoToTest = string.Empty;
var nullTestResult = PhoneAreaAttribute.IsValid(nullToTest);
var emptyTestResult = PhoneAreaAttribute.IsValid(emptoToTest);
Assert.IsTrue(nullTestResult, "Null Test should return true.");
Assert.IsTrue(emptyTestResult, "Empty Test should return true.");
}
}
When considering how to "correctly" test this class, consider the following:
The cyclomatic complexity (CC) of IsValid is 5.
The method relies on two other methods IsNullOrWhiteSpace and LengthBetween. I believe both of these have an additional CC of 2.
There is the chance of throwing an InvalidCastException. This represents another potential test case.
In total, you have potentially 8 cases in which you need to test. Using xUnit.net and Fluent Assertions* (you could do something similar in NUnit as well), you could write the following unit tests to "correctly" test this method:
public class PhoneAreaAttributeTests
{
[Theory]
[InlineData("123", true)]
[InlineData(" ", true)]
[InlineData(null, true)]
public void IsValid_WithCorrectInput_ReturnsTrue(
object value, bool expected)
{
// Setup
var phoneAreaAttribute = CreatePhoneAreaAttribute();
// Exercise
var actual = phoneAreaAttribute.IsValid(value);
// Verify
actual.Should().Be(expected, "{0} should be valid input", value);
// Teardown
}
[Theory]
[InlineData("012", false)]
[InlineData("A12", false)]
[InlineData("1", false)]
[InlineData("12345", false)]
public void IsValid_WithIncorrectInput_ReturnsFalse(
object value, bool expected)
{
// Setup
var phoneAreaAttribute = CreatePhoneAreaAttribute();
// Exercise
var actual = phoneAreaAttribute.IsValid(value);
// Verify
actual.Should().Be(expected, "{0} should be invalid input", value);
// Teardown
}
[Fact]
public void IsValid_UsingNonStringInput_ThrowsExcpetion()
{
// Setup
var phoneAreaAttribute = CreatePhoneAreaAttribute();
const int input = 123;
// Exercise
// Verify
Assert.Throws<InvalidCastException>(
() => phoneAreaAttribute.IsValid(input));
// Teardown
}
// Simple factory method so that if we change the
// constructor, we don't have to change all our
// tests reliant on this object.
public PhoneAreaAttribute CreatePhoneAreaAttribute()
{
return new PhoneAreaAttribute();
}
}
*I like using Fluent Assertions, and in this case it helps because we can specify a message to let us know when an assert fails, which one is the failing assertion. These data-driven tests are nice in that they can reduce the number of similar test methods we would need to write by grouping various permutations together. When we do this it is a good idea to avoid Assertion Roulette by the custom message as explained. By the way, Fluent Assertions can work with many testing frameworks.
I'm using Moq and I have the following interface:
public interface IGameBoard : IEnumerable<PieceType>
{
...
}
public class GameBoardNodeFactory
{
public virtual GameBoardNode Create (int row, int column, IGameBoard gameBoard)
{
...
}
}
Then I have a test like this:
var clonedGameBoardMock = new Mock<IGameBoard> (MockBehavior.Loose);
var gameBoardNodeFactoryMock = new Mock<GameBoardNodeFactory> ();
gameBoardNodeFactoryMock.Setup (x =>
x.Create (
position.Row,
position.Column,
clonedGameBoardMock.Object)).Returns (new GameBoardNode { Row = position.Row, Column = position.Column });
But then gameBoardNodeFactoryMock.Object.Create (position.Row, position.Column, clonedGameBoardMock.Object) throws a NullReferenceException. I tried to create a mock for the IGameBoard such that it doesn't extend IEnumerable<PieceType> interface and then it works.
Any help is appreciated.
You would need to create a Setup for GetEnumerator() if it's being called. Something like:
var mockPieces = new List<PieceType>;
clonedGameBoardMock.Setup(g => g.GetEnumerator()).Returns(mockPieces.GetEnumerator());
Note sure if that's the issue in this case, but worth noting if you ever need to mock IEnumerable<T>.
The answer by #DanBryant was also the key to our solution. However, the enumerator in that case might be accidentally reused. Instead, I suggest using:
clonedGameBoardMock.Setup(g => g.GetEnumerator()).Returns(() => mockPieces.GetEnumerator());
Here's a full repro (new class library using NUnit 2.6.4 and Moq 4.2):
public interface IMyThing<T> : IEnumerable<T>
{
string Name { get; set; }
IMyThing<T> GetSub<U>(U key);
}
public interface IGenericThing
{
string Value { get; set; }
}
public class Pet
{
public string AnimalName { get; set; }
}
public class Unit
{
public IEnumerable<Pet> ConvertInput(IMyThing<IGenericThing> input)
{
return input.GetSub("api-key-123").Select(x => new Pet { AnimalName = x.Value });
}
}
[TestFixture]
public class Class1
{
[Test]
public void Test1()
{
var unit = new Unit();
Mock<IMyThing<IGenericThing>> mock = new Mock<IMyThing<IGenericThing>>();
Mock<IMyThing<IGenericThing>> submock = new Mock<IMyThing<IGenericThing>>();
var things = new List<IGenericThing>(new[] { new Mock<IGenericThing>().Object });
submock.Setup(g => g.GetEnumerator()).Returns(() => things.GetEnumerator());
mock.Setup(x => x.GetSub(It.IsAny<string>())).Returns(submock.Object);
var result = unit.ConvertInput(mock.Object);
Assert.That(result, Is.Not.Null.And.Not.Empty);
Assert.That(result, Is.Not.Null.And.Not.Empty); // This would crash if the enumerator wasn't returned through a Func<>...
}
}
For what it's worth / to make this question pop up to that one lone Googler with the same problem I had: the above is an abstracted version of the Couchbase .NET client's IView<T> interface, which also implements IEnumerable<T>.
A null reference in this situation usually means your setup was never met. Meaning it was never called with the exact values you set it up for. To debug this I would make your match less constraining by using It.IsAny() and so on to make sure the test will match on any call to the mocked function. In most cases this is good enough. Any reason why your are trying to match on specific values?
Okay if anyone is interested, I updated Moq to version 4 and now everything works as expected.
I have a method in a service which I want to test. That method calls another method in the same class. This method is already tested so I want to mock that method.
This is my setup:
private readonly Mock<INewsLetterRepository> _mockNewsLetterRepository;
private readonly Mock<INewsLetterService> _mockNewsLetterService;
private readonly INewsLetterService _newsLetterService;
public NewsLetterServiceTest()
{
_mockNewsLetterRepository = new Mock<INewsLetterRepository>();
_mockNewsLetterService = new Mock<INewsLetterService> {CallBase = true};
_newsLetterService = new NewsLetterService(_mockNewsLetterRepository.Object);
}
And this is the test I am using:
[TestMethod]
public void CreateNewsLetter_Should_Return_Empty_NewsLetter()
{
var template = new Template
{
PlaceHolders = new List<TemplatePlaceholder>()
};
var newsLetter = new NewsLetter {Template = template};
const string content = "<html><body><!--BROWSER--></body></html>";
_mockNewsLetterService.Setup(x => x.BuildNewsLetterHTML(It.IsAny<NewsLetter>())).Returns(content);
var actual = _mockNewsLetterService.Object.CreateNewsLetter(newsLetter);
Assert.AreEqual(content, actual);
}
Now the problem is that the function I am mocking: BuildNewsLetterHTML returns null instead of the content it supposed to return.
Here is a simplified version of the function I want to test:
public string CreateNewsLetter(NewsLetter newsLetter)
{
var newsletterHTML = BuildNewsLetterHTML(newsLetter);
return newsletterHTML;
}
So the problem is that, at least as I see it, is that the function I mock doesn't return the content string it supposed to return. The test fails on Assert.AreEqual because the actual is null. Any of you have any idea why actual is null?
Thanks in advance.
It seems the problem is you are calling Mock<T>'s CreateNewsLetter method which has not been set up, and which also seems to be your method under test. You are not supposed test against your fakes, they are supposed to substitute out production code to assist in testing other code.
I suggest you use the extract and override pattern in this case, since you are wanting to cause fake implementation in a method of the same class that has a method under test.
Moq is great in some cases but I don't think there is anything wrong with using a small readable stub when the situation calls for it.
public class YourTestClass
{
[TestMethod]
public void CreateNewsLetter_Should_Return_Empty_NewsLetter()
{
var template = new Template
{
PlaceHolders = new List<TemplatePlaceholder>()
};
var newsLetter = new NewsLetter { Template = template };
const string content = "<html><body><!--BROWSER--></body></html>";
INewsletterService service = new BuildNewsLetterStub(content);
string actual = service.CreateNewsLetter(newsLetter);
Assert.AreEqual(content, actual);
}
}
public class BuildNewsLetterStub : NewsLetterService
{
private string _letter;
public BuildNewsLetterStub(string letter)
{
_letter = letter;
}
public override string BuildNewsLetterHTML(NewsLetter newsLetter)
{
return _letter;
}
}
To override BuildNewsLetterHTML it must be marked virtual.