Why are no query parameters being passed to my NancyFX module? - c#

I am running a self-hosted NancyFX web server inside of my application. Right now I have one module hosted:
public class MetricsModule : NancyModule
{
private IStorageEngine _storageEngine;
public MetricsModule(IStorageEngine storageEngine) : base("/metrics")
{
_storageEngine = storageEngine;
Get["/list"] = parameters =>
{
var metrics = _storageEngine.GetKnownMetrics();
return Response.AsJson(metrics.ToArray());
};
Get["/query"] = parameters =>
{
var rawStart = parameters.start;
var rawEnd = parameters.end;
var metrics = parameters.metrics;
return Response.AsJson(0);
};
}
}
My Bootstrapper class is:
public class OverlookBootStrapper : DefaultNancyBootstrapper
{
private readonly IStorageEngine _storageEngine;
public OverlookBootStrapper(IStorageEngine storageEngine)
{
_storageEngine = storageEngine;
}
protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
container.Register(_storageEngine);
}
}
I am trying to test it with the following test:
[TestInitialize]
public void Init()
{
_storageEngine = new Mock<IStorageEngine>();
var bootstrapper = new OverlookBootStrapper(_storageEngine.Object);
_browser = new Browser(bootstrapper);
}
[TestMethod]
public void Query_Builds_Correct_Query_From_Parameters()
{
var metric = new Metric("device", "category", "name", "suffix");
var startDate = DateTime.Now;
var endDate = DateTime.Now.AddMinutes(10);
var path = "/metrics/query";
var response = _browser.Get(path, with =>
{
with.HttpRequest();
with.Query("start", startDate.ToString());
with.Query("end", endDate.ToString());
with.Query("metrics", metric.ToParsableString());
});
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, "Incorrect status code returned");
_storageEngine.Verify(x => x.ExecuteQuery(It.Is<Query>(y => y.StartDate == startDate)), Times.Once());
_storageEngine.Verify(x => x.ExecuteQuery(It.Is<Query>(y => y.EndDate == endDate)), Times.Once());
_storageEngine.Verify(x => x.ExecuteQuery(It.Is<Query>(y => y.Metrics.Contains(metric))), Times.Once());
}
When this test is debugged and a breakpoint is put on return Response.AsJson(0);, I inspected the parameters object and noticed that parameters.Count is zero, and all 3 values are null.
What am I doing incorrectly?
Edit: When I bring up this endpoint in the web browser, the same issue occurs. I get a result of 0 sent back to my browser, but when debugging I see that no query string parameters I specify have been recognized by NancyFX.

The parameters argument to your lambda contains the route parameters you captured in the in your Get["/query"]. In this case nothing. See #thecodejunkie's comment for an example where there is something.
To get to the query paramters use Request.Query. That's also a dynamic and will contain whatever query parameters was in the request. Like so:
Get["/query"] = parameters =>
{
var rawStart = Request.Query.start;
var rawEnd = Request.Query.end;
var metrics = Request.Query.metrics;
return Response.AsJson(0);
};
This should work with your tests too.

You can let NancyFx's model binding take care of the url query string.
public class RequestObject
{
public string Start { get; set; }
public string End { get; set; }
public string Metrics { get; set; }
}
/query?start=2015-09-27&end=2015-10-27&metrics=loadtime
Get["/query"] = x =>
{
var request = this.Bind<RequestObject>();
}

Related

mock elastic search innerhits

I have read the document https://gist.github.com/netoisc/5d456850d79f246685fee23be2469155
which well know how to mock elasticsearch query
But I have a case which return result have innerhits
Documents = searchResult.Hits.Select(
h => {
if (h.InnerHits.TryGetValue("books", out var data)) {
ht.Source.Books = data!.Documents<book>();
}
ht.Source.Books = ht.Source.Books.Where(k=>k.country=="US");
return h.Source;
})
From my mock test
I have do this
var innerHitResult = new Mock<InnerHitsResult>();
innerHitResult.SetupGet(s => s.Documents<book>()).Returns(new List<book>());
var innerHitDictionary = new Dictionary<string, InnerHitsResult> {
{
"books", innerHitResult.Object
}
};
I've got the error on innerHitResult.SetupGet , which error say :
System.ArgumentException: Expression is not a property access: s => s.Documents<book>()
Even I use innerHitResult.Setup is not working
Can I know how to do mock for inner hit ?
In the other simple example
if I have a class :
public class BlogSearchResult
{
public InnerMetaData Hits { get; set; }
public IEnumerable<T> Document<T>() where T : class => Hits.Documents<T>();
}
I want to mock BlogSearchResult which want to do
var blogs = fixture.CreateMany<Blog>();
var blogSearch = new Mock<BlogSearchResult>();
blogSearch.SetupGet(s => s.Document<Blog>()).Returns(blogs);
or
blogSearch.Setup(s => s.Document<Blog>()).Returns(blogs);
They are all return error, is that possible ?

Testing FluentValidation ChildRules

Given the following object:
public class PatchDTO
{
public PatchDTO()
{
Data = new List<Datum>();
}
public List<Datum> Data { get; set; }
public class Datum
{
public Datum()
{
Attributes = new Dictionary<string, object>();
}
public string Id { get; set; }
public Dictionary<string, object> Attributes { get; set; }
}
}
I have my validator set as follows:
RuleFor(oo => oo.Data)
.NotEmpty()
.WithMessage("One or more Data blocks must be provided");
RuleForEach(d => d.Data).ChildRules(datum =>
{
datum.RuleFor(d => d.Id)
.NotEmpty()
.WithMessage("Invalid 'Data.Id' value");
});
Which I'm trying to test using the test extensions as such:
[Theory]
[InlineData(null)]
[InlineData("")]
public void Id_Failure(string id)
{
dto.Data[0].Id = id;
var result = validator.TestValidate(dto);
result.ShouldHaveValidationErrorFor(oo => oo.Data[0].Id)
.WithErrorMessage("Invalid 'Data.Id' value");
}
But when I run the test it says:
FluentValidation.TestHelper.ValidationTestException
HResult=0x80131500
Message=Expected a validation error for property Id
----
Properties with Validation Errors:
[0]: Data[0].Id
But as you can see under the 'Validation Errors', it has actually picked up in the validation failure but isn't tying it to this test. So how do I test these ChildRules or tell the test extension method which property it should actually be checking?
(I also used the validator.ShouldHaveValidationErrorFor directly with the same results)
I've had this problem before and resorted to using the string overload for ShouldHaveValidationErrorFor
The following (nunit) test passes
[TestCase(null)]
[TestCase("")]
public void Id_InvalidValue_HasError(string id)
{
var fixture = new Fixture();
var datum = fixture.Build<PatchDTO.Datum>().With(x => x.Id, id).Create();
var dto = fixture.Build<PatchDTO>().With(x => x.Data, new List<PatchDTO.Datum> { datum }).Create();
var validator = new PatchDTOValidator();
var validationResult = validator.TestValidate(dto);
validationResult.ShouldHaveValidationErrorFor("Data[0].Id")
.WithErrorMessage("Invalid 'Data.Id' value");
}
It's been a while since I looked at it, but I believe the issue is in the extension ShouldHaveValidationErrorFor matching on property name and the property expression overload doesn't resolve the property name to 'Data[0].Id'. If you inspect the validation results you'll get a ValidationError object that looks something like this
{
"PropertyName":"Data[0].Id",
"ErrorMessage":"Invalid 'Data.Id' value",
"AttemptedValue":"",
"CustomState":null,
"Severity":0,
"ErrorCode":"NotEmptyValidator",
"FormattedMessageArguments":[
],
"FormattedMessagePlaceholderValues":{
"PropertyName":"Id",
"PropertyValue":""
},
"ResourceName":null
}
EDIT:
Had a quick peek into the property expression overload, as per below
public IEnumerable<ValidationFailure> ShouldHaveValidationErrorFor<TProperty>(Expression<Func<T, TProperty>> memberAccessor)
{
return ValidationTestExtension.ShouldHaveValidationError(this.Errors, ValidatorOptions.PropertyNameResolver(typeof (T), memberAccessor.GetMember<T, TProperty>(), (LambdaExpression) memberAccessor), true);
}
Presumably you could use another/write your own property name resolver to handle the case as it is settable. You'd probably have to dig into the expression to do it.

Use workflow to evaluate dynamic expression

I would like to pass an object and expression into a dynamically created workflow to mimic the Eval function found in many languages. Can anyone help me out with what I am doing wrong? The code below is a very simple example if taking in a Policy object, multiple its premium by 1.05, then return the result. It throws the exception:
Additional information: The following errors were encountered while processing the workflow tree:
'DynamicActivity': The private implementation of activity '1: DynamicActivity' has the following validation error: Value for a required activity argument 'To' was not supplied.
And the code:
using System.Activities;
using System.Activities.Statements;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Policy p = new Policy() { Premium = 100, Year = 2016 };
var inputPolicy = new InArgument<Policy>();
var theOutput = new OutArgument<object>();
Activity dynamicWorkflow = new DynamicActivity()
{
Properties =
{
new DynamicActivityProperty
{
Name="Policy",
Type=typeof(InArgument<Policy>),
Value=inputPolicy
}
},
Implementation = () => new Sequence()
{
Activities =
{
new Assign()
{
To = theOutput,
Value=new InArgument<string>() { Expression = "Policy.Premium * 1.05" }
}
}
}
};
WorkflowInvoker.Invoke(dynamicWorkflow);
}
}
public class Policy
{
public int Premium { get; set; }
public int Year { get; set; }
}
}
You can use Workflow Foundation to evaluate expressions, but it is far easier to use almost any other option.
The key issue at play with your code was that you were not trying to evaluate the expression (with either VisualBasicValue or CSharpValue). Assigning InArgument`1.Expression is an attempt to set the value - not to set the value to the result of an expression.
Keep in mind that compiling expressions is fairly slow (>10ms), but the resultant compiled expression can be cached for quick executions.
Using Workflow:
class Program
{
static void Main(string[] args)
{
// this is slow, only do this once per expression
var evaluator = new PolicyExpressionEvaluator("Policy.Premium * 1.05");
// this is fairly fast
var policy1 = new Policy() { Premium = 100, Year = 2016 };
var result1 = evaluator.Evaluate(policy1);
var policy2 = new Policy() { Premium = 150, Year = 2016 };
var result2 = evaluator.Evaluate(policy2);
Console.WriteLine($"Policy 1: {result1}, Policy 2: {result2}");
}
}
public class Policy
{
public double Premium, Year;
}
class PolicyExpressionEvaluator
{
const string
ParamName = "Policy",
ResultName = "result";
public PolicyExpressionEvaluator(string expression)
{
var paramVariable = new Variable<Policy>(ParamName);
var resultVariable = new Variable<double>(ResultName);
var daRoot = new DynamicActivity()
{
Name = "DemoExpressionActivity",
Properties =
{
new DynamicActivityProperty() { Name = ParamName, Type = typeof(InArgument<Policy>) },
new DynamicActivityProperty() { Name = ResultName, Type = typeof(OutArgument<double>) }
},
Implementation = () => new Assign<double>()
{
To = new ArgumentReference<double>() { ArgumentName = ResultName },
Value = new InArgument<double>(new CSharpValue<double>(expression))
}
};
CSharpExpressionTools.CompileExpressions(daRoot, typeof(Policy).Assembly);
this.Activity = daRoot;
}
public DynamicActivity Activity { get; }
public double Evaluate(Policy p)
{
var results = WorkflowInvoker.Invoke(this.Activity,
new Dictionary<string, object>() { { ParamName, p } });
return (double)results[ResultName];
}
}
internal static class CSharpExpressionTools
{
public static void CompileExpressions(DynamicActivity dynamicActivity, params Assembly[] references)
{
// See https://learn.microsoft.com/en-us/dotnet/framework/windows-workflow-foundation/csharp-expressions
string activityName = dynamicActivity.Name;
string activityType = activityName.Split('.').Last() + "_CompiledExpressionRoot";
string activityNamespace = string.Join(".", activityName.Split('.').Reverse().Skip(1).Reverse());
TextExpressionCompilerSettings settings = new TextExpressionCompilerSettings
{
Activity = dynamicActivity,
Language = "C#",
ActivityName = activityType,
ActivityNamespace = activityNamespace,
RootNamespace = null,
GenerateAsPartialClass = false,
AlwaysGenerateSource = true,
ForImplementation = true
};
// add assembly references
TextExpression.SetReferencesForImplementation(dynamicActivity, references.Select(a => (AssemblyReference)a).ToList());
// Compile the C# expression.
var results = new TextExpressionCompiler(settings).Compile();
if (results.HasErrors)
{
throw new Exception("Compilation failed.");
}
// attach compilation result to live activity
var compiledExpression = (ICompiledExpressionRoot)Activator.CreateInstance(results.ResultType, new object[] { dynamicActivity });
CompiledExpressionInvoker.SetCompiledExpressionRootForImplementation(dynamicActivity, compiledExpression);
}
}
Compare to the equivalent Roslyn code - most of which is fluff that is not really needed:
public class PolicyEvaluatorGlobals
{
public Policy Policy { get; }
public PolicyEvaluatorGlobals(Policy p)
{
this.Policy = p;
}
}
internal class PolicyExpressionEvaluator
{
private readonly ScriptRunner<double> EvaluateInternal;
public PolicyExpressionEvaluator(string expression)
{
var usings = new[]
{
"System",
"System.Collections.Generic",
"System.Linq",
"System.Threading.Tasks"
};
var references = AppDomain.CurrentDomain.GetAssemblies()
.Where(a => !a.IsDynamic && !string.IsNullOrWhiteSpace(a.Location))
.ToArray();
var options = ScriptOptions.Default
.AddImports(usings)
.AddReferences(references);
this.EvaluateInternal = CSharpScript.Create<double>(expression, options, globalsType: typeof(PolicyEvaluatorGlobals))
.CreateDelegate();
}
internal double Evaluate(Policy policy)
{
return EvaluateInternal(new PolicyEvaluatorGlobals(policy)).Result;
}
}
Roslyn is fully documented, and has the helpful Scripting API Samples page with examples.

Mock method in Parallel.ForEach always returns null

I have the following code:
public int LoadFilesAndSaveInDatabase(string filesPath)
{
var calls = new ConcurrentStack<GdsCallDto>();
var filesInDirectory = this._directoryProxy.GetFiles(filesPath);
if (filesInDirectory.Any())
{
Parallel.ForEach(filesInDirectory, file =>
{
var lines = this._fileProxy.ReadAllLines(file, Encoding.Unicode);
if (lines.Any())
{
// Reads the file and setup a new DTO.
var deserializedCall = this._fileManager.DeserializeFileContent(lines, Path.GetFileName(file));
// Insert the DTO in the database.
this._gdsCallsData.InsertOrUpdateGdsCall(deserializedCall);
// We keep track of the dto to count the number of restored items.
calls.Push(deserializedCall);
}
});
}
return calls.Count;
}
And I have the following unit test:
[TestMethod]
public void ShouldLoadFilesAndSaveInDatabase()
{
// Arrange
var path = RandomGenerator.GetRandomString(56);
var encoding = Encoding.Unicode;
var fileNameEnvironment = RandomGenerator.GetRandomString();
var fileNameModule = RandomGenerator.GetRandomString();
var fileNameRecordLocator = RandomGenerator.GetRandomString(6);
var fileNameTimestamp = RandomGenerator.GetRandomDateTime().ToString("O").Replace(':', 'o');
// We simulate the presence of 4 files.
var files = new List<string>
{
RandomGenerator.GetRandomString(255),
RandomGenerator.GetRandomString(255),
RandomGenerator.GetRandomString(255),
RandomGenerator.GetRandomString(255)
}.ToArray();
var expectedResult = 4;
this._directoryProxy.Expect(d => d.GetFiles(path))
.Return(files);
this._fileProxy.Expect(f => f.ReadAllLines(path, encoding))
.Return(files).Repeat.Times(files.Length);
// Act
var result = this._databaseReloadManager.LoadFilesAndSaveInDatabase(path);
// Assert
Assert.AreEqual(result, expectedResult);
this._directoryProxy.AssertWasCalled(d => d.GetFiles(path));
this._fileProxy.AssertWasCalled(f => f.ReadAllLines(path, Encoding.Unicode));
}
The problem is on the following line:
var lines = this._fileProxy.ReadAllLines(file, Encoding.Unicode);
Even though I set an expectation and a return value, when I run the unit test, it always returns null.
I am using Rhino.Mocks, it works perfectly fine elsewhere but not there.
I had a look at some discussions here but none of them helped. Can it be due to the use of Parallel.ForEach? Is there a way of doing such a mock?
If you need any other info, please let me know.
I don't think there is a problem with the Parallelization. It seems your problem is related to the proxy instance setup with Rhino Mock.
Ensure what you pass into the parameters of the ReadAllLines are the same as you call them when it run through the production code.
this._fileProxy.Expect(f => f.ReadAllLines(path, encoding))
.Return(files).Repeat.Times(files.Length);
For instance if you setup on different path and the value of that path diefferent when test executes you may see NULL in return. But again hard to tell without seeing the full setup/constructor in the code. Also check the random generators see what has been used in each time.
The below is I sort of put together and working for me.
Working means I don't get NULL for:
var lines = this._fileProxy.ReadAllLines(file, Encoding.Unicode);
//some dummy code so I can compile
public interface IProxyDir
{
IEnumerable<string> GetFiles(string path);
}
public class GdsCallDto
{
}
public class Proxy : IProxyDir
{
public IEnumerable<string> GetFiles(string path)
{
throw new NotImplementedException();
}
}
public interface IFileDir
{
IEnumerable<string> ReadAllLines(string path, Encoding encoding);
}
public class FileProxy : IFileDir
{
public IEnumerable<string> ReadAllLines(string path, Encoding encoding)
{
throw new NotImplementedException();
}
}
public interface IFileMgr
{
string DeserializeFileContent(IEnumerable<string> lines, string content);
}
public class FileMgr : IFileMgr
{
public string DeserializeFileContent(IEnumerable<string> lines, string content)
{
throw new NotImplementedException();
}
}
//system under test
public class Sut
{
private IProxyDir _directoryProxy;
private IFileDir _fileProxy;
private IFileMgr _fileManager;
public Sut(IProxyDir proxyDir, IFileDir fileProxy, IFileMgr mgr)
{
_fileManager = mgr;
_directoryProxy = proxyDir;
_fileProxy = fileProxy;
}
public int LoadFilesAndSaveInDatabase(string filesPath)
{
var calls = new ConcurrentStack<GdsCallDto>();
var filesInDirectory = this._directoryProxy.GetFiles(filesPath);
if (filesInDirectory.Any())
{
Parallel.ForEach(filesInDirectory, file =>
{
var lines = this._fileProxy.ReadAllLines("ssss", Encoding.Unicode);
if (lines.Any())
{
// Reads the file and setup a new DTO.
var deserializedCall = this._fileManager.DeserializeFileContent(lines, Path.GetFileName("file"));
// Insert the DTO in the database.
//this._gdsCallsData.InsertOrUpdateGdsCall(deserializedCall);
// We keep track of the dto to count the number of restored items.
//calls.Push(deserializedCall);
}
});
}
return 1;
}
}
Sample Unit Test
[TestClass]
public class UnitTest1
{
private IProxyDir _directoryProxy;
private IFileDir _fileProxy;
private IFileMgr _fileMgr;
private Sut _sut;
public UnitTest1()
{
_directoryProxy = MockRepository.GenerateMock<IProxyDir>();
_fileProxy = MockRepository.GenerateMock<IFileDir>();
_fileMgr = MockRepository.GenerateMock<IFileMgr>();
}
[TestMethod]
public void ShouldLoadFilesAndSaveInDatabase()
{
// Arrange
var path = RandomGenerator.GetRandomString(56);
var encoding = Encoding.Unicode;
var fileNameEnvironment = RandomGenerator.GetRandomString(5);
var fileNameModule = RandomGenerator.GetRandomString(5);
var fileNameRecordLocator = RandomGenerator.GetRandomString(6);
var fileNameTimestamp = RandomGenerator.GetRandomDateTime().ToString("O").Replace(':', 'o');
// We simulate the presence of 4 files.
var files = new List<string>
{
RandomGenerator.GetRandomString(255),
RandomGenerator.GetRandomString(255),
RandomGenerator.GetRandomString(255),
RandomGenerator.GetRandomString(255)
}.ToArray();
var expectedResult = 4;
this._directoryProxy.Expect(d => d.GetFiles(path))
.Return(files);
this._fileProxy.Expect(f => f.ReadAllLines(path, encoding))
.Return(files).Repeat.Times(files.Length);
_sut = new Sut(_directoryProxy, _fileProxy, _fileMgr);
// Act
var result = this._sut.LoadFilesAndSaveInDatabase(path);
// Assert
Assert.AreEqual(result, expectedResult);
this._directoryProxy.AssertWasCalled(d => d.GetFiles(path));
this._fileProxy.AssertWasCalled(f => f.ReadAllLines(path, Encoding.Unicode));
}
}
internal class RandomGenerator
{
public static string GetRandomString(int number)
{
return "ssss";
}
public static DateTime GetRandomDateTime()
{
return new DateTime();
}
}
I could get rid of this issue, probably caused by the use of random values. I am now calling the method IgnoreArguments() on my expectation:
this._fileProxy.Expect(f => f.ReadAllLines(path, encoding))
.Return(files).Repeat.Times(files.Length).IgnoreArguments();
It does the trick (i.e. the unit test is running successfully), but I do not know if it is very elegant.

How do I properly test an API Controller that returns json for a non null response?

I have this test method for testing an API controller, that returns a JSON string, for a non null response.
[TestClass]
public class TransactionsTests
{
[TestMethod]
public void ColorPerformance_GetChartData_NotNullResponse_Test()
{
// Arrange
string quality = null, cars = null, year = "2015";
var listColorPerformanceChartData = new List<ColorPerformanceChartData>();
var mockRepository = new Mock<IColorPerformanceRepository>();
mockRepository.Setup(x => x.GetChartData(quality, cars, year))
.Returns(listColorPerformanceChartData);
var controller = new ColorPerformanceController(mockRepository.Object);
// Act
IHttpActionResult actionResult = controller.GetChartData(quality, cars, year);
var contentResult = actionResult as OkNegotiatedContentResult<object>;
// Assert
Assert.IsNotNull(contentResult);
Assert.IsNotNull(contentResult.Content);
}
}
This test is passing in that contentResult is not null. However, I am not feeling sure that the test is written properly for the following reasons:
contentResult.Content has empty data, in that there is no data being returned from _repository.GetChartData() method, but is not empty because still the json constructed is as follows:
{ categories = {int[0]}, series = { name = "Number of colors", data = {double[0]} } }
contentResult.ContentNegotiator, contentResult.Formatter and contentResult.Request all are throwing an exception of InvalidOperationException with the message HttpControllerContext.Configuration must not be null. I don't know why this is happening.
The API Controller:
public class ColorPerformanceController : ApiController
{
private IColorPerformanceRepository _repository;
public ColorPerformanceController(IColorPerformanceRepository repository)
{
_repository = repository;
}
public IHttpActionResult GetChartData(string quality, string cars, string year)
{
try
{
var data = ProcessData(quality, cars, year);
return Ok(data);
}
catch (Exception ex)
{
return InternalServerError(ex);
}
}
private object ProcessData(string quality, string cars, string year)
{
var data = _repository.GetChartData(quality, cars, year);
return new {
categories = data.Select(d => d.Id).ToArray(),
series = new[] { new { name = "Number of colors", data = data.Select(d => d.CumulativePercentage).ToArray() }}
};
}
}
IColorPerformanceRepository:
public interface IColorPerformanceRepository
{
IEnumerable<ColorPerformanceChartData> GetChartData(string quality, string cars, string year);
}
The object returned from the repository implementation:
public class ColorPerformanceChartData
{
private double _cumulativePercentage;
public double CumulativePercentage {
get { return Math.Round(_cumulativePercentage, 2); }
set { _cumulativePercentage = value; }
}
public int Id { get; set; }
}
What am I missing or doing wrong here?
Best practice is you should avoid using anonymous type in this case:
private object ProcessData(string quality, string cars, string year)
{
var data = _repository.GetChartData(quality, cars, year);
return new {
categories = data.Select(d => d.Id).ToArray(),
series = new[] { new { name = "Number of colors", data = data.Select(d => d.CumulativePercentage).ToArray() }}
};
}
Try defining a class for it so that you can de-serialize the string and check each property:
// Act
IHttpActionResult actionResult = controller.GetChartData(quality, cars, year);
//Notice I use YourClass instead of object here.
var contentResult = actionResult as OkNegotiatedContentResult<YourClass>;
// Assert
Assert.IsNotNull(contentResult);
Assert.IsNotNull(contentResult.Content);
//Assert all properties of contentResult.Content like categories, series,..
Regarding the exception, try:
var controller = new ColorPerformanceController(mockRepository.Object);
//Add these 2 lines
controller.Request = new HttpRequestMessage();
controller.Configuration = new HttpConfiguration();
From http://www.asp.net/web-api/overview/testing-and-debugging/unit-testing-controllers-in-web-api

Categories

Resources