Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I unit test a C# function which returns a Func<something>?

I have a class containing a method which returns a Result object which contains a property of type Func.

class Result {
   public Func<Result> NextAction { get; set; }
}

How do I write a unit test assertion regarding the content of this Func? The following obviously does not work, because the compiler generates two different methods for the lambda:

// Arrange
ListController controller = new ListController(domain);
// Act
Result actual = controller.DefaultAction();
// Assert
Func<Result> expected = () => new ProductsController(domain).ListAction();
Assert.That(actual.NextAction, Is.EqualTo(expected));

I'm guessing that I could do this by using expression trees instead, but... is there a way to avoid doing so? I'm using NUnit 2.5.

EDIT: There are no other identifying fields in the Result object. It is intended to be a way of invoking the next object/method based on a decision made in the current object/method.

like image 742
goofballLogic Avatar asked Mar 22 '10 12:03

goofballLogic


People also ask

Can you unit test C?

The most scalable way to write unit tests in C is using a unit testing framework, such as: CppUTest. Unity. Google Test.

How do you run a unit test?

To run all the tests in a default group, choose the Run icon and then choose the group on the menu. Select the individual tests that you want to run, open the right-click menu for a selected test and then choose Run Selected Tests (or press Ctrl + R, T).

What are the three steps in a unit test?

The idea is to develop a unit test by following these 3 simple steps: Arrange – setup the testing objects and prepare the prerequisites for your test. Act – perform the actual work of the test. Assert – verify the result.


2 Answers

Why not invoke the Func and compare the returned values?

var actualValue = actual.NextAction();
var expectedValue = expected();
Assert.That(actualValue, Is.EqualTo(expectedValue));

EDIT: I see that the Result class does not have any identity. I guess you have some other fields in the Result class that define the identity of the Result and can be used to determine if two results are equal.

like image 126
Marek Avatar answered Oct 15 '22 13:10

Marek


I'm not aware of an easy way to look inside a lambda (other than using expression trees as you said) but it is possible to compare delegates if they're assigned a method group instead.

var result1 = new Result {
    NextAction = new ProductsController(domain).ListAction };
var result2 = new Result {
    NextAction = new ProductsController(domain).ListAction };

//objects are different
Assert.That(result1, Is.Not.EqualTo(result2));

//delegates are different
Assert.That(result1.NextAction, Is.Not.EqualTo(result2.NextAction));

//methods are the same
Assert.That(result1.NextAction.Method, Is.EqualTo(result2.NextAction.Method));

The above example does not work if you use lambdas since they are compiled to different methods.

like image 39
Nathan Baulch Avatar answered Oct 15 '22 13:10

Nathan Baulch