I am writing a testing framework for my system, which allows users to create mocked inputs to the system. The system manipulates that input, and updates some of its members for later post processing.
In order to allow users to mock the input, I need to be able to update a mocked input's members. Furthermore, the input may not be a mock, so I would prefer a solution oblivious to the type of element received.
Simply put, I have a function which receives an object and attempts to set one of its properties:
func(object a)
a.m = 5;
Which I want to test by mocking its input a, using the Moq library. Unfortunately, my test failed, since mocked objects' members need to be set using Mock.SetUpGet, instead of standard member assignment.
What would be a good way to test such a function, without changing it?
In order to be able to mock and test it, the property must be virtual, but if that's the case you can use the SetupSet method, rather than SetupGet:
public class A
{
public virtual int m { get; set; }
}
[TestFixture]
public class Tests
{
public static void SetProperty(A a)
{
a.m = 5;
}
[Test]
public void IsThePropertySet()
{
var x = new Mock<A>();
x.SetupSet<int>(a => a.m = 5).Verifiable();
SetProperty(x.Object);
x.Verify();
}
}
Your function should have getters and setters anyway.
And a good way of testing whether your functions work is to do a small-scale test. Initialize an object and send that in to your method, seeing whether it does what you want.
public class myClass
{
public int number;
public void setNumber(int nNum)
{
number = nNum;
}
public int getNumber()
{
return number;
}
}
class Program
{
static void myMethod(myClass obj, int nNumb)
{
//obj.setNumber(nNumb);
obj.number = nNumb;
}
static void Main(string[] args)
{
myClass myObj = new myClass();
myMethod(myObj, 3);
//Console.WriteLine(myObj.getNumber());
Console.WriteLine(myObj.number);
Console.ReadLine();
}
}
}
Output: 3
Related
I have written the xUnit test cases in C#. That test class contains so many methods. I need to run the whole test cases in a sequence. How can I set the test case sequence in xUnit?
In xUnit 2.* this can be achieved using the TestCaseOrderer attribute to designate an ordering strategy, which can be used to reference an attribute that is annotated on each test to denote an order.
For example:
Ordering Strategy
[assembly: CollectionBehavior(DisableTestParallelization = true)]
public class PriorityOrderer : ITestCaseOrderer
{
public IEnumerable<TTestCase> OrderTestCases<TTestCase>(IEnumerable<TTestCase> testCases) where TTestCase : ITestCase
{
var sortedMethods = new SortedDictionary<int, List<TTestCase>>();
foreach (TTestCase testCase in testCases)
{
int priority = 0;
foreach (IAttributeInfo attr in testCase.TestMethod.Method.GetCustomAttributes((typeof(TestPriorityAttribute).AssemblyQualifiedName)))
priority = attr.GetNamedArgument<int>("Priority");
GetOrCreate(sortedMethods, priority).Add(testCase);
}
foreach (var list in sortedMethods.Keys.Select(priority => sortedMethods[priority]))
{
list.Sort((x, y) => StringComparer.OrdinalIgnoreCase.Compare(x.TestMethod.Method.Name, y.TestMethod.Method.Name));
foreach (TTestCase testCase in list)
yield return testCase;
}
}
static TValue GetOrCreate<TKey, TValue>(IDictionary<TKey, TValue> dictionary, TKey key) where TValue : new()
{
TValue result;
if (dictionary.TryGetValue(key, out result)) return result;
result = new TValue();
dictionary[key] = result;
return result;
}
}
Attribute
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class TestPriorityAttribute : Attribute
{
public TestPriorityAttribute(int priority)
{
Priority = priority;
}
public int Priority { get; private set; }
}
Test Cases
[TestCaseOrderer("FullNameOfOrderStrategyHere", "OrderStrategyAssemblyName")]
public class PriorityOrderExamples
{
[Fact, TestPriority(5)]
public void Test3()
{
// called third
}
[Fact, TestPriority(0)]
public void Test2()
{
// called second
}
[Fact, TestPriority(-5)]
public void Test1()
{
// called first
}
}
xUnit 2.* ordering samples here
Testpriority: at the bottom of this page.
[PrioritizedFixture]
public class MyTests
{
[Fact, TestPriority(1)]
public void FirstTest()
{
// Test code here is always run first
}
[Fact, TestPriority(2)]
public void SeccondTest()
{
// Test code here is run second
}
}
BTW, I have the same problem right now. And yes, it is not the clean art.. but QA wanted a manual test.. so an automated test with a specific order already is a big leap for them.. (cough) and yes, it is not really unit testing..
If you really have the need to prioritize your tests (probably not your unit tests) you can use Xunit.Priority.
I have used it for some integration testing and works really well and simple without the overhead of having to write your prioritization classes, for simple case scenarios
For some reason, XUnit.Priority didn't work for me. In my test cases, it wasn't running the tests in the priority order specified.
So I tried XUnitPriorityOrderer, which is similar to use but was working (To quickly test it, save the following code in a text editor as OrderedXUnitTests.linq, then open it with LinqPad 6 and execute it. Alternatively, you can also copy the TestClass to Visual Studio and add XUnit, XUnit.Runner.VisualStudio and XUnitPriorityOrderer):
<Query Kind="Program">
<NuGetReference>XUnitPriorityOrderer</NuGetReference>
<Namespace>Xunit</Namespace>
<Namespace>XUnitPriorityOrderer</Namespace>
</Query>
#load "xunit"
// using XUnitPriorityOrderer
// see: https://github.com/frederic-prusse/XUnitPriorityOrderer
void Main()
{
RunTests(); // Call RunTests() or press Alt+Shift+T to initiate testing.
}
#region private::Tests
[TestCaseOrderer(CasePriorityOrderer.TypeName, CasePriorityOrderer.AssembyName)]
public class TestClass
{
static List<string> Order { get; set; }
public TestClass()
{
Order = Order ?? new List<string>();
}
[Fact, Order(2)]
void Test_Xunit_AnotherTest()
{
Order.Add("Test_Xunit_AnotherTest");
Assert.True(3 + 1 == 4);
}
[Fact, Order(1)]
void Test_Xunit()
{
Order.Add("Test_XUnit");
Assert.True(1 + 1 == 2);
}
[Fact, Order(99)]
void Print_Order()
{
Order.Add("Print_Order");
var strOrder = string.Join(", ", Order.ToArray());
strOrder.Dump("Execution Order");
Assert.True(true);
}
}
#endregion
This will run the tests in given order (Order(1), Order(2) and then Order(99)) and will dump the executed tests finally (test method Print_Order()).
You can't, by design. It's deliberately random in order to prevent anyone getting one of those either by desire or by accident.
The randomness is only for a given Test class, so you may be able to achieve your goals by wrapping items you want to control the order of inside a nested class - but in that case, you'll still end up with random order whenever you have more than two Test Methods in a class.
If you're trying to manage the building up of fixtures or context, the built-in IUseFixture<T> mechanism may be appropriate. See the xUnit Cheat Sheet for examples.
But you really need to tell us more about what you're trying to do or we'll just have to get speculative.
I have test that check ref parameter value from event that raised after the change. The test work fine when I create real class but when I try mocked class its fail. Simple code example:
[TestClass]
public class Fixture
{
[TestMethod]
public void CheckRealClass()
{
// this test passed
var classToTest = new NumberChangerClass();
CheckClass(classToTest);
}
[TestMethod]
public void CheckMockedClass()
{
// this test failed
var classToTest = new Mock<NumberChangerClass>() { CallBase = true };
CheckClass(classToTest.Object);
}
private void CheckClass(NumberChangerClass numberChangerClass)
{
// Arrange
var number = 1;
numberChangerClass.StorageChanged += (sender, args) =>
{
Assert.AreEqual(2, number);
};
// Act
numberChangerClass.SetValue(ref number, 2);
}
}
public class NumberChangerClass
{
public event EventHandler StorageChanged;
public virtual void SetValue(ref int storage, int newValue)
{
storage = newValue;
StorageChanged?.Invoke(this, null);
}
}
In CheckMockedClass the number is actually changed but only after the the code exits from SetValue method.
I use Moq version 4.2.1409.1722 but it doesn't work also in the latest version (4.8.1).
There is a way to make CheckMockedClass to pass?
UPDATE:
I've opened issue in moq github: link
short answer: there nothing that can be done about it.
more details:
the behaviour you are observing is a direct consequence of how DynamicProxy (which Moq depends on) handles by-reference parameters during method call interception (which is documented at https://github.com/castleproject/Core/blob/master/docs/dynamicproxy-by-ref-parameters.md): Arguments are buffered in a separate location during call interception and only written back at the end of interception, that's why refparameters are updated in a delayed / deferred manner. There is unfortunately nothing that can be done about it.
I still try to find a way to get the updated number when I check Assert.AreEqual(2, number);
According to documentation
Reference Moq Quickstart
Ended up having to make the event virtual on the concrete class as that is what Moq can work with. If how ever it was defined on an interface, it would work out of the box.
public class NumberChangerClass {
public virtual event EventHandler StorageChanged;
public virtual void SetValue(ref int storage, int newValue) {
storage = newValue;
StorageChanged?.Invoke(this, null);
}
}
In order to mock it and raise the event.
delegate void SetValueCallback(ref int storage, int newValue);
[TestMethod]
public void CheckMockedClass() {
var classToTest = new Mock<NumberChangerClass>() { CallBase = true };
// callbacks for methods with `ref` / `out` parameters are
//possible but require some work (and Moq 4.8 or later):
classToTest
.Setup(_ => _.SetValue(ref It.Ref<int>.IsAny, It.IsAny<int>()))
.Callback(new SetValueCallback((ref int storage, int newValue) => {
storage = newValue;
classToTest.Raise(_ => _.StorageChanged += null, EventArgs.Empty);
}));
CheckClass(classToTest.Object);
}
Which is actually mimicking what is done in the base method, hence my concern about mocking the class under test.
This has a code smell to it and would advise reviewing the current design of the code being tested.
I have discovered a fantastic way to unit test private methods.
This is great except I don't like how the method name is typed in as a string. Is there a way to create a "safety net?" I want to type the method name so that the compiler can throw a compiler time error if the method does not exist on an object.
Private method:
public class BankAccount
{
//Private method to test
private bool VerifyAmount(double amount)
{
return (amount <= 1000);
}
}
Unit Test:
[TestMethod()]
public void VerifyAmountTest()
{
//Using PrivateObject class
PrivateObject privateHelperObject = new PrivateObject(typeof(BankAccount));
double amount = 500F;
bool expected = true;
bool actual;
actual = (bool)privateHelperObject.Invoke("VerifyAmount", amount);
Assert.AreEqual(expected, actual);
}
I know that some people think that we should not unit test private methods. That is not the purpose of this question so let's not discuss that question and stay on topic.
When you unit-test a class, you are essentially putting your consumer hat and calling the exposed methods of the class to verify that the class does what it claims to do.
For instance, consider this example using your BankAccount class:
public class BankAccount
{
public Widthdrawal WithdrawMoney(double amount)
{
if(!VerifyAmount(amount))
throw new InvalidOperationException("Minimum dispensed is $1,000!");
//Do some stuff here
return new Withdrawal(1000);
}
private bool VerifyAmount(double amount)
{
return (amount <= 1000);
}
}
You can then test for a few things. For instance:
That a valid amount results in a withdrawal.
That an invalid amount results in an invalid operation exception.
Your tests:
[TestMethod]
public void Verify_Valid_Amount_Results_In_Widtdrawal()
{
var bankAccount = new BankAccount();
var withdrawal = bankAccount.WithdrawMoney(1200);
Assert.IsNotNull(withdrawal);
Assert.AreEqual(1200, withdrawal);
}
[TestMethod]
[ExpectedException(typeof(InvalidOperationException))]
public void Verify_Valid_Amount_Results_In_Exception()
{
var bankAccount = new BankAccount();
var withdrawal = bankAccount.WithdrawMoney(800);
}
As you can see, you test the funcionality that uses the private method, not the private method itself.
If it's important for you to verify that method, you can either make it public or abstract the concept of amount verification to another class that exposes this method and can be unit tested separately.
Am I right that you want check presence of private method on .Net object?
Then pick one of the following cases to extract any method from instance:
Case 1 If you don't care about method signature:
var typeOfObj = typeof(BancAccount)
.GetMethods(
BindingFlags.NonPublic |
BindingFlags.Instance)
.Any( method => method.Name == testedName )
Case 2 If you need specify exact signature then use - typeof(BancAccount).GetMethod(testedName, <types of arguments>)
I'm planning to store all test cases in a excel file with columns indicate test method names, parameters and expected results; however, I found TestCaseSource simply assigns all test cases to every test method. I'm wondering that is there any way I can make NUnit select test cases for methods base on method names I put in the spreadsheet?
Thanks.
There is a way to do this.
For example, as you mentioned, you can create a custom attribute.
The idea is to pass name of test to TestCaseSource.
You can do it by creating TestCaseSource as separate class.
First, TestCaseSource class:
public class SpreadSheetTestCaseSource
{
[ThreadStatic]
public static string TestName = String.Empty;
public static IEnumerable TestCases
{
get
{
SpreadSheetTestCaseProvider.GetTestCases()
.Where(testCase => testCase.TestName == TestName);
}
}
}
Then attribute:
public class MyTestCaseSourceAttribute : TestCaseSourceAttribute
{
public MyTestCaseSourceAttribute(Type sourceType, string sourceName,
[CallerMemberName] string name = null)
: base(sourceType, sourceName)
{
SpreadSheetTestCaseSource.TestName = name;
}
//Another two members impl.
}
And test:
[TestFixture]
public class TestClass
{
[MyTestCaseSource(typeof(SpreadSheetTestCaseSource), "TestCases")]
public void TestMethod()
{
//Test logic
}
}
SpeadSheetTestCaseSource.TestName is thread static. So you can run tests parallel.
This isn't a feature that NUnit supports directly. The various TestCaseSource type attributes have no ability to feed a test method based on the input.
An option would be to create a TestCaseSource for each of your test methods. Each of these would be a simple wrapper that passes in the method name to a single internal method. That internal method would read in the Excel file and only return the rows for the given method name.
PseudoCode;
[TestCaseSource(nameof(TestMethodOneSource))]
public void TestMethodOne(int x, int y, int expected)
{
Assert.That(x + y, Is.EqualTo(expected));
}
public static IEnumerable<object[]> TestMethodOneSource() =>
ReadExcel(nameof(TestMethodOne));
private static IEnumerable<object[]> ReadExcel(string method)
{
// Open and start reading Excel
for(var row in rows)
{
if(row[0] == method)
{
// Return objects minus the method
yield return new [] {row[1], ..., row[n]};
}
}
}
Here is the code:
public interface IAccessPoint
{
int BackHaulMaximum { get; set; }
bool BackHaulMaximumReached();
void EmailNetworkProvider();
}
public class AccessPoint : IAccessPoint
{
public int BackHaulMaximum { get; set; }
public bool BackHaulMaximumReached()
{
if (BackHaulMaximum > 80)
{
EmailNetworkProvider();
return true;
}
return false;
}
public void EmailNetworkProvider()
{
}
}
//Test
[Test]
public void NetworkProviderShouldBeEmailedWhenBackHaulMaximumIsReached()
{
var apMock = MockRepository.GenerateMock<IAccessPoint>();
apMock.Stub(x => x.BackHaulMaximum).Return(81);
Assert.AreEqual(true, apMock.BackHaulMaximumReached());
apMock.AssertWasCalled(x => x.EmailNetworkProvider());
}
You shouldn't be mocking the class that you are testing. You should only be mocking the classes that class under test depends on. Something like this:
public interface IAccessPoint
{
int BackHaulMaximum { get; set; }
bool BackHaulMaximumReached();
void EmailNetworkProvider();
}
public class AccessPoint : IAccessPoint
{
private IMailProvider Mailer { get; set; }
public AccessPoint( IMailProvider provider )
{
this.Mailer = provider ?? new DefaultMailProvider();
}
public int BackHaulMaximum { get; set; }
public bool BackHaulMaximumReached()
{
if (BackHaulMaximum > 80)
{
EmailNetworkProvider();
return true;
}
return false;
}
public void EmailNetworkProvider()
{
this.Mailer.SendMail(...);
}
}
[Test]
public void NetworkProviderShouldBeEmailedWhenBackHaulMaximumIsReached()
{
var mailerMock = MockRepository.GenerateMock<IMailProvider>();
mailerMock .Expect( m => m.SendMail( ... specify argument matches ... ) );
var accessPoint = new AccessPoint( mailerMock );
accessPoint.BackHaulMaximum = 81;
Assert.IsTrue( accessPoint.BackHaulMaximumReached() );
mailerMock.VerifyAllExpectations();
}
I agree with tvanfosson's answer. 99% (maybe 100%) of the time, you won't want a mock for your SUT.
However the reason it is failing is because your call:
Assert.AreEqual(true, apMock.BackHaulMaximumReached());
is not going to result in the actual method BackHaulMaximumReached() being called! It's going to call the mock's method.
Edit
If it wasn't clear, that means that BackHaulMaximumReached() will (I think) return the default value for its return type, which is "false" in the case of bools. So you need to stub out that method to return true to get the Assert.AreEqual to to pass (which is not a good test as I said).
Your next assertion will then fail, as EmailNetworkProvider() will never get called (again, because you are calling the mock's methods, not the actual SUT's methods).
I would change the code as follows:
//Test
[Test]
public void NetworkProviderShouldBeEmailedWhenBackHaulMaximumIsReached()
{
var mockRepo = new MockRepository();
var apMock = mockRepo.PartialMock<AccessPoint>();
using (mockRepo.Record())
{
Expect.Call(apMock.EmailNetworkProvider).Repeat.Once();
}
using (mockRepo.Playback())
{
apMock.BackHaulMaximum = 81;
Assert.AreEqual(true, apMock.BackHaulMaximumReached());
}
mockRepo.VerifyAll();
}
What you're expecting is that given the input to the class, when you call a method, another method that induces some unwanted side effects is also called. You want to mock the side-effect-inducing behavior, but you want to exercise the rest of the actual logic.
The solution is a PartialMock. It allows the mocking behavior to be applied to only the members of the mocked class that you specify. You can use it in several syntaxes, but the safest, most reliable method is to record and playback expectations rather than call the Expects() method on the mock itself.
We are using it here to expect a call on our method that we want to mock; expecting the call will cause the actual method not to be called. Then, the class is exercised, and the logic of the actual class is used (hence the assertion in our test succeeds), but when the call to our expected method is reached, what is actually called is the mocked method that updates some internal counters. Then, VerifyAll() asserts that all expectations happened according to the settings prescribed.