The problem I want to solve is, how to test two dependent classes in C#. For testing I'm using NUnit and Moq.
Let's say I have a custom collection which autonumerates its items. Values inside collection must be kept in its original order, so that's the reason why it has to be autonumerated. Following code shows the most simple example of mentioned classes:
public interface ICustomItem
{
int Id { get; set; }
ICustomCollection<ICustomItem> ParentCollection { get; set; }
}
public interface ICustomCollection<T> where T : ICustomItem
{
IEnumerable<T> Items { get; set; }
void Add(T t);
// And more of course...
}
public class CustomCollection<T> : ICustomCollection<T> where T : ICustomItem
{
public IEnumerable<T> Items { get; set; }
public void Add(T t)
{
// Some logic here...
t.Id = Items.Count(); // Generate Id
}
}
When adding item to collection, a new Id is generated and assigned to CustomItem. Mechanism of autonumerating should be included also in other methods, such as Remove(), but for this question I've left Add method only.
The question is, how to test if autonumerates works correctly? When the mock is passed as a param, it is not modified inside the class. Should I test the class with simple instance of created-for-tests CustomItem class?
tl;dr
In other words, I want to be able to modify a mock inside a class.
Try to use the class in the test just as you would use it from the production code. This will give you the most usable test in the sense that you are free to refactor the code inside the classes without breaking or even changing a test. The test will also serve as an example on how to use the class.
To start out I would not use Moq, but rather use a short MockCustomItem class that you implement just for the test.
Then use add some values and assert that result is what you expected. Make it a habit to only use one assert in each test like below.
[TestFixture]
public class GivenCustomCollectionWithTwoElements
{
private CustomCollection<MockCustomItem> _customCollection;
[SetUp]
public void SetUp()
{
_customCollection = new CustomCollection<MockCustomItem>();
_customCollection.Add(new MockCustomItem());
_customCollection.Add(new MockCustomItem());
}
[Test]
public void CheckLength()
{
Assert.That(_customCollection.Items, Is.EqualTo(2));
}
[Test]
public void CheckFirstItemId()
{
Assert.That(_customCollection.Items.ElementAt(0).Id, Is.EqualTo(0));
}
[Test]
public void CheckSecondItemId()
{
Assert.That(_customCollection.Items.ElementAt(1).Id, Is.EqualTo(1));
}
private class MockCustomItem : ICustomItem
{
public int Id { get; set; }
public ICustomCollection<ICustomItem> ParentCollection { get; set; }
}
}
Once you get the hang of this, you can also use Moq to create more concise tests with less boilerplate code. In this case NUnit parameterizedtest cases could also be used.
In unit tests you shall only test the unit you are testing right now. So I wold say that you shall mock/fake the ICustomItem and send it in and then looks if the faked object get the Id you expect.
Read my answer here for further info about the same topic Any ASP.NET (WebForm) apps which have good unit tests (CodePlex or anywhere)?
I use FakeItEasy as mock/fake-framework but I guess moq would look pretty similar, here is my code for it
[TestFixture]
public class CustomCollectionTests{
[Test]
public void Add_AddTwoItems_ItemsGetsConsecutiveIds() {
var customItem1 = A.Fake<ICustomItem>();
var customItem2 = A.Fake<ICustomItem>();
var cutomCollection = new CustomCollection<ICustomItem>();
cutomCollection.Add(customItem1);
cutomCollection.Add(customItem2);
Assert.AreEqual(1, customItem1.Id);
Assert.AreEqual(2, customItem2.Id);
}
}
public interface ICustomItem {
int Id { get; set; }
}
public interface ICustomCollection<T> where T : ICustomItem {
void Add(T t);
}
public class CustomCollection<T> : ICustomCollection<T> where T : ICustomItem {
public List<T> innerList = new List<T>();
public void Add(T t) {
// Some logic here...
innerList.Add(t);
t.Id = innerList.Count(); // Generate Id
}
}
Edit
Removed non tested MOQ-example that seemed to be not working.
You're right in the fact that the mock isn't modified. But you should be able to verify the mock after calling the add method like this:
mock.VerifySet(x => x.Id = 42);
Remember to set something in the Items property before calling Add. That something should return 42, when asking for the Count(). That could be a mock as well.
Related
Is there a good tool under C#, to fake complex interfaces (service, repository and the like) with partial test implementations?
The mock framework I am currently using (RhinoMocks) is too slow and too hard to handle for this purpose.
Prerequisites:
No significant performance penalty, compared to real implementations (bulk tests)
Implementation with rudimentary logic and data (e.g.: dictionary instead of database table)
No need to change the tests, when the interface changes.
Full implementation example:
public interface IMyInterface
{
int PropertyA { get; set; }
int PropertyB { get; set; }
void DoSomethingWithX(int x);
int GetValueOfY();
}
public class FakeImplementation : IMyInterface
{
private int _valueOfYCalls = 0;
public int PropertyA { get; set; }
public int PropertyB { get; set; }
public void DoSomethingWithX(int x)
{ }
public int GetValueOfY()
{
return _valueOfYCalls++;
}
}
The counter is just to simulate the rudimentary logic.
Problem is, if the interface gets a new method, like SetSomeZ(int z) , the test won't build/run anymore, without explicit change.
Is there a fake/mock framework, working with basic implementations, but adding members automatically, either via virtual/override, or wrapper?
Such as this:
[ImplementsInterface(nameof(IMyInterface))]
public class FakeImplementationBase
{
private int _valueOfYCalls = 0;
[ImplementsMember(nameof(IMyInterface.GetValueOfY))]
public virtual int GetValueOfY()
{
return _valueOfYCalls++;
}
}
The tool/framework should generate full implementation types at runtime, similar to mocks/stubs, but using the basic implementation, just adding the missing interface parts.
This is not supposed to be for real unit testing, but for more complex purposes. It's also legacy software with huge interfaces and classes, not much about "single responsibility".
Moq is exactly what you want.
public interface IFoo {
int MethodA(int a);
void MethodB(long b);
void MethodC(string c);
...
}
var MoqFoo = new Mock<IFoo>();
MoqFoo.Setup(m => m.MethodA(It.Is(a => a > 0)).Returns<int>(a => a + 1);
MoqFoo.Setup(m => m.MethodC(It.IsAny<string>()).Callback<string>(c => Debug.Write(c));
Note how we didn't do .Setup() for MethodB? When you declare it, all methods and properties get dummy methods/properties, .Setup() will specify your own custom ones.
So if your interface has 10 methods but you only want to test MethodD(), you only need to write code for that.
http://www.developerhandbook.com/unit-testing/writing-unit-tests-with-nunit-and-moq/
I have implemented array based Stack Data Structure along with corresponding Unit Tests. This Stack implements my IStack interface. So at the moment, my UT class looks something like that:
[TestClass]
public class Stack_ArrayBased_Tests
{
//check against empty collection
[TestMethod]
public void IsEmpty_NoElements()
{
var myStack = new Stack_ArrayBased_Example1(10);
var exp = true;
var act = myStack.IsEmpty();
Assert.AreEqual(exp, act);
}
Now, I am about to implement Linked List based Stack. This Stack will inherit from the same IStack interface.
I would like to Unit Test the linked list Stack as well. Since both are inheriting from the same interface, I should be able to take advantage of already implemented Unit Test, in order to prevent from unnecessary code duplication.
What would be the best way to create two separate Unit Test classes, one for Array based Stack, and another for Linked List based Stack, that would use the same Unit Test methods? I assume Dependency Injection would be an answer, but how I would go about it?
Dependency injection is never the answer when it comes to tests.
You are not testing abstractions, that's impossible, you test concrete implementations. You can however mock abstractions, interfaces, abstract classes.
You can create some class with the sole purpose of reusing code and you call that class from your test methods, that's ok and totally doable.
You will still need two test classes, one for each of your concrete implementations, and have both call this new class you created. This avoids code duplication.
You can separate logic in another method.
[TestMethod]
public void IsEmpty_NoElements_ArrayBased()
{
var myStack = new Stack_ArrayBased_Example1(10);
IsEmpty_NoElements(myStack)
}
[TestMethod]
public void IsEmpty_NoElements_LinkedListBased()
{
var myStack = new Stack_LinkedListBased_Example1(10);
IsEmpty_NoElements(myStack)
}
public void IsEmpty_NoElements(IStack myStack)
{
var exp = true;
var act = myStack.IsEmpty();
Assert.AreEqual(exp, act);
}
Say we have the following
public interface IStack
{
bool IsEmpty { get; }
}
public class StackImpl1 : IStack
{
public StackImpl1(int size)
{
IsEmpty = true;
}
public bool IsEmpty { get; }
}
public class StackImpl2 : IStack
{
public StackImpl2(int size)
{
IsEmpty = true;
}
public bool IsEmpty { get; }
}
And we wish to implement the IsEmpty_OnCreation() test from the OP. We can make a common test and add multiple invokers (one for each implementation to be tested). The problem is scaling.
For each new piece of functionality to be tested we need to add
1) the test implementation
2) an invoker for each implementation to be tested.
For each new implementation we introduce, we need to add an invoker for each existing test.
It is possible to use inheritance to do most of the work for us
public abstract class StackTest
{
protected abstract IStack Create(int size);
[TestMethod]
public void IsEmpty_NoElements()
{
var myStack = Create(10);
var exp = true;
var act = myStack.IsEmpty;
Assert.AreEqual(exp, act);
}
}
[TestClass]
public class StackImp1Fixture : StackTest
{
protected override IStack Create(int size)
{
return new StackImpl1(size);
}
}
[TestClass]
public class StackImp2Fixture : StackTest
{
protected override IStack Create(int size)
{
return new StackImpl2(size);
}
}
The tests are generated in each derived fixture.
If we want to add a new test, we add it to the StackTest class and it is automatically included in each derived fixture.
If we add a third implementation of IStack , we simply add a new test fixture deriving from StackTest and overriding the create method.
Note:
If the classes under test have default constructors, the same shape can be used with a Generic StackTest as the base
public class GenStackTest<TStack> where TStack : IStack, new()
{
[TestMethod]
public void IsEmpty_NoElements()
{
var myStack = new TStack();
var exp = true;
var act = myStack.IsEmpty;
Assert.AreEqual(exp, act);
}
}
[TestClass]
public class GenStack1Fixture : GenStackTest<StackImpl1>
{
}
[TestClass]
public class GenStack2Fixture : GenStackTest<StackImpl2>
{
}
Is there any way to retrieve the fake objects which were inserted into a faked class?
E.g.
Let's say I have the following interface + class;
public interface IFakeable
{
void FakeYou();
}
public class SomeClass
{
private readonly IFakeable _fake;
public SomeClass(IFakeable fake)
{
_fake = fake;
}
public void FakeCall()
{
_fake.FakeYou();
}
}
And wanted to test something like the following:
[TestFixture]
public class SomeClassTests
{
[Test]
public void FakeCall_CallsIFakeabl_FakeYou()
{
var subject = A.Fake<SomeClass>();
subject.FakeCall();
A.CallTo(() => A.Fake<IFakeable>().FakeYou()).MustHaveHappened();
}
}
Is this possible without exposing the SomeClass._fake field?
Is there somewhere I can specify to use Singletons for Fakes?
If the subject of the test is SomeClass, why are you faking it? You want to test the actual class, not a fake... So you should probably do this:
[Test]
public void FakeCall_CallsIFakeabl_FakeYou()
{
var fake = A.Fake<IFakeable>();
var subject = new SomeClass(fake);
subject.FakeCall();
A.CallTo(() => fake.FakeYou()).MustHaveHappened();
}
Alternatively, you could use FakeItEasy's fixture initialization feature:
[TestFixture]
public class SomeClassTests
{
[Fake] public IFakeable Fake {get;set;}
[UnderTest] public SomeClass Subject {get;set;}
[SetUp]
public void Setup()
{
Fake.InitializeFixture(this);
}
[Test]
public void FakeCall_CallsIFakeabl_FakeYou()
{
Subject.FakeCall();
A.CallTo(() => Fake.FakeYou()).MustHaveHappened();
}
}
What's more important here is why you're looking to test a method that is called on a private field. The private field is encapsulated in the class, therefore anything the method does on that field constitutes "internals of the class" and isn't relevant to testing. I presume that the FakeYou() implementation has some important side effect that requires testing. In that case, I would test for that side effect following the subject.FakeCall(), rather than testing that the FakeCall has happened.
Alternatively, you can change _fake to be a public field, and change:
A.CallTo(() => A.Fake<IFakeable>().FakeYou()).MustHaveHappened();
to:
A.CallTo(() => subject._fake.FakeYou()).MustHaveHappened();
You might want to rename "_fake" as "Fake" if this is the case for C# conventions, as ReSharper will tell you.
I tried to make a unit-testing of a class User
I tried to do it with an interface, but I did not understand exactly what is and if it is the correct way to do the test, so:
My Class User
public class User : IUser
{
public int id { get; private set; }
public string username { get; set; }
public IUser user;
public User(IUser userI) // constructor with interface
{
user = userI;
}
public virtual bool MyFunction(string test)
{
if(test=="ping")
return true;
else
return false;
}
}
My Interface IUser
public interface IUser
{
int id { get; }
string username { get; set; }
}
And then my Unit-test
[TestFixture]
public class MoqTest
{
[Test]
public void TestMyFunction()
{
var mock = new Mock<IUser>();
User user = new User(mock.Object);
var result = user.MyFunction("ping");
Assert.That(result, Is.EqualTo(true));
}
}
The test result is correct and actually returns true, but do not understand the way of using the interface.
Basically by mocking you create some kind of a dummy-implementation for that interface. So when calling Mock<IUser>() the compiler generates an anonymous class that implements the interface IUser and returns a new instance of this class. Now when creating your User-object you inject that dummy-object. The mocked object has no behaviour, all its members are set to to their default-value, it is only guaranteed that theay are set to anything. You can also change the values your members return but that won´t affect your example.
This way you can test the method you´re interested in without having to implement any external dependeines. This can be necessary because you have currently no working instance for the IUSer-interface and implement it later or because its initialization is quite heavy and you want to avoid initialize it within your tests (think of some database-logic included that does not affect your actual test, but would be needed to run the test).
In your case you could even use new User(null) as the method to be tested does not rely on an instance of that interface at all. So you won´t even have to mock it at all.
I have a base class called "Question" and several child classes such as "TrueFalse", "MultipleChoice", "MatchPairs" etc...
The base class has methods with logic that all of the child classes use, such as sending off scores and raising events.
I have set my unit tests up for the child classes but I am not sure how I can setup unit tests for the methods in the base class.
I did some searching and I understand I need to create a Mock of the class but I am not sure how to do this as I have only seen how to do this on an instantiable object.
I have Moq & NUnit installed in project so ideally id like to use this. I am still new to programming and this is my first time adding unit tests so I appreciate any advice you can give me.
I did a search on site first and found a couple of similar questions but they did not give any example on how to do it, just that it needed to be mocked.
Many thanks.
From this answer it looks like what you need is something along these lines:
[Test]
public void MoqTest()
{
var mock = new Moq.Mock<AbstractBaseClass>();
// set the behavior of mocked methods
mock.Setup(abs => abs.Foo()).Returns(5);
// getting an instance of the class
var abstractBaseClass = mock.Object;
// Asseting it actually works :)
Assert.AreEqual(5, abstractBaseClass.Foo());
}
I was trying to mock an abstract class and this way didn't worked for me.
what did work was to create a new class that extended the abstract class
class newclass : abstractClass
{
}
like this I could set the property and test the main method
There is no simple way to test it,
The best option is:
mark base class methods as virtual
create test classes for each of the "TrueFalse", "MultipleChoice", "MatchPairs" classes with virtual methods overridden and invoke public Abstract method.
So for example you have next inheritance structure
class Question {
protected virtual bool CheckCorrect(params int[] answers){
return answers.Any(x => x== 42);
}
}
class TrueFalse: Question {
public int SelectedAnswer {get;set;}
public bool IsCorrect(){
return CheckCorrect(SelectedAnswer );
}
}
class MultipleChoice: Question {
public int[] SelectedAnswers {get;set;}
public bool IsCorrect(){
return CheckCorrect(SelectedAnswers );
}
}
Test methods for this:
abstract class TrueFalseTest: TrueFalseTest{
public abstract bool CheckCorrectReal(params int[] answers);
public override bool CheckCorrect(params int[] answers){
return CheckCorrect(SelectedAnswer );
}
}
abstract class MultipleChoiceTest: MultipleChoice {
public abstract bool CheckCorrectReal(params int[] answers);
public override bool CheckCorrect(params int[] answers){
return CheckCorrect(SelectedAnswer );
}
}
And test methods itself:
class TestQuestionForms{
[Fact]
public void TrueFalseTest_ShouldExecute_CheckCorrectReal()
{
//setup
var mock = new Mock<TrueFalseTest>();
mock.Setup(q => q.CheckCorrectReal(It.IsAny<int[] answers>))
.Returns(true);
//action
mock.Object.IsCorrect();
//assert
mock.Verify(db => db.CheckCorrectReal());
}
[Fact]
public void MultipleChoiceTest_ShouldExecute_CheckCorrectReal()
{
//setup
var mock = new Mock<MultipleChoiceTest>();
mock.Setup(q => q.CheckCorrectReal(It.IsAny<int[] answers>))
.Returns(true);
//action
mock.Object.IsCorrect();
//assert
mock.Verify(db => db.CheckCorrectReal());
}
}