I'm currently working on many .NET Core API projects and encountered a future possible regression.
How do you guys prevent this situation ?
Here's my architecture :
API project
BusinessLayer
API.UnitTests (references 2))
API.IntegrationTests (references 1 #for the casts))
An integration test example :
[Fact]
public async Task TestGetAll()
{
// Arrange
var query = "api/v1/xxx/getall";
// Act
var response = await _AuthorizedClient.GetAsync(query);
// Assert
Assert.True(response.IsSuccessStatusCode);
var results = JsonConvert
.DeserializeObject<List<MyResult>>(await response.Content.ReadAsStringAsync());
Assert.True(results.Any());
//Assert.AnythingOn(results);
}
Considering the next version and/or my [colleague] maintenance; with my deserializing cast, an update of the MyResult object might be hidden and create a production regression.
I've tried to do my integration test with the dynamic keyword and without casting but it take my much effort.
How do you deal with this situation ?
Are there any best practices ?
[Edit] After some search, I've found this article Differential Regression Testing for REST APIs which looks quite interesting
In my experience, dynamic is not a good practice because it will never fail on build but will fail on execution.
I think you should use something like this :
public static T DeserializeObject<T>(string value)
{
T result = default(T);
try {
result = JsonConvert.DeserializeObject<T>(value);
}
return result;
}
Related
I've migrated concepts from a couple of CQRS frameworks I've seen and just started facing some issues.
I have a common EntityDbContext subclass which I use in any consuming project without further extension to suit the domain of the application, rather I provide interfaces, IReadEntities and IWriteEntities which have methods like Query() and Get() which behind the scenes call Set() returning the DbSet() then allowing the standard LINQ expressions to be chained on as for any EF query. I'm facing issues around using Include() on my IQueryables as I'm using LinqKit with AsExpandable() at the end of all my calls. This is what my context Query methods look like
public new IQueryable<TEntity> Query<TEntity>() where TEntity : class, IEntity
{
// AsNoTracking returns entities that are not attached to the DbContext
return QueryUnfiltered<TEntity>().Where(_recordAuthority.Clause<TEntity>());
}
public IQueryable<TEntity> QueryUnfiltered<TEntity>() where TEntity : class, IEntity
{
// AsNoTracking returns entities that are not attached to the DbContext
return Set<TEntity>().AsNoTracking().AsExpandable();
}
A typical query handler looks like this:
public async Task<IEnumerable<GetCustomerView>> Handle(CustomersBy query, CancellationToken cancellationToken)
{
var customers = _db.Query<Customer>();
// Apply filters
if (!string.IsNullOrEmpty(query.FirstName))
customers = customers.Where(x => x.FirstName.Contains(query.FirstName));
if (!string.IsNullOrEmpty(query.LastName))
customers = customers.Where(x => x.LastName.Contains(query.LastName));
// Execute the query and return the results
var view = await customers.Select(x => new GetCustomerView
{
Id = x.Id,
FirstName = x.FirstName,
LastName = x.LastName,
EmailAddress = x.EmailAddress
}).ToListAsync(cancellationToken).ConfigureAwait(false) as IEnumerable<GetCustomerView>;
return view;
}
This scenario works fine if I wanted to pull address details from a related table as I use projection on the database serve given I'm using the Select prior to execution. There are scenarios though where it makes sense to pull an object graph back and specify Include(...) statements but as it stands specifying _db.Query<Customer>().Include(c => c.Address) doesn't hydrate the Address navigation property. I've tried leaving the AsExpandable() off and then the results come back.
The question is, does anyone see a way to allow the Include statements to be provided maybe as a parameter to the method and then I loop through them and tack them on before calling AsExpandable()? I can't quite get my head around how to do it, if it's possible.
Maybe there's another approach?
Interestingly this apparently works fine on a version of this pattern a colleague uses where they are using EF 6. He says they specify Include after the AsExpandable without a problem.
This is known issue with EF Core and LinqKit AsExpandable (and in general with any extension library which uses custom IQueryProvider to perform its query expression tree preprocessing like LinqKit), because EF Core ignores all EF Core specific IQueryable extensions (Include / ThenInclude, AsNoTracking etc.) it the query provider is different (or does not inherit) the EF Core one (EF6 has no such requirements).
With that being said, currently there is no other solution than applying all EF Core specific extensions before calling AsExpandable.
Ok this works. I created an overload:
public IQueryable<TEntity> Query<TEntity, TProperty>(IEnumerable<Expression<Func<TEntity, TProperty>>> includes) where TEntity : class, IEntity
{
var query = Set<TEntity>().AsNoTracking();
foreach (var expression in includes)
{
query = query.Include(expression);
}
return query.AsExpandable();
}
From my handler I create a list of include expressions and pass to the Query:
var includes = new List<Expression<Func<Customer, object>>>
{
c => c.Address
};
var customers = _db.Query(includes);
var result = await customers.ToListAsync(cancellationToken).ConfigureAwait(false);
Execution of the query has the navigation property populated:
Means I'm not 'Fluent'ly chaining them from the client code's perspective, but I don't think it's terrible.
Thoughts?
I am using Masstransit to send Request/Response via servicebus between two services(dont ask why).
I would like to set-up custom application insights telemetry. I know that ServiceBus Messages add Diagnostic metadata so consumer can extract it and use it to add correlation between services. However I can't access it in MassTransit, or at least I dont know how.
Any tips?
Couple of months passed and solution i implemented proves to be a good one.
I created class that implements IReceiveObserver. On PreReceive I am able to access (ServiceBusReceiveContext)context and start Telemetry operation that has correct parent id. so it looks like this:
public Task PreReceive(ReceiveContext context)
{
var serviceBusContext = (ServiceBusReceiveContext)context;
var requestActivity = new Activity("Process");
requestActivity.SetParentId(serviceBusContext.Properties["Diagnostic-Id"].ToString());
IOperationHolder<RequestTelemetry> operation = _telemetryClient.StartOperation<RequestTelemetry>(requestActivity);
operation.Telemetry.Success = true;
serviceBusContext.Properties.Add(TelemetryOperationKey, operation);
return Task.CompletedTask;
}
On PostReceive I am able to stop operation:
public Task PostReceive(ReceiveContext context)
{
var serviceBusContext = (ServiceBusReceiveContext)context;
var operation = (IOperationHolder<RequestTelemetry>)serviceBusContext.Properties[TelemetryOperationKey];
operation.Dispose();
return Task.CompletedTask;
}
I also do some magic when exception happens:
public Task ReceiveFault(ReceiveContext context, Exception exception)
{
_telemetryClient.TrackException(exception);
var serviceBusContext = (ServiceBusReceiveContext)context;
var operation = (IOperationHolder<RequestTelemetry>)serviceBusContext.Properties[TelemetryOperationKey];
operation.Telemetry.ResponseCode = "Fail";
operation.Telemetry.Success = false;
operation.Dispose();
return Task.CompletedTask;
}
It was difficult to find this solution by reading MassTransit documentation. I would say that MassTransit is a fantastic tool for some situations there is no alternatives. However documentation is pretty poor.
You can use Application Insights with MassTransit, there is a package available that writes metrics directly.
The documentation is available here:
https://masstransit-project.com/advanced/monitoring/applications-insights.html
Also, you can access Activity.Current from anyway, I think, based on my experience with DiagnosticSource. It might be different with AppInsights though.
In learning about the area handling story in MVC6, I keep coming across blog posts that have area:exists in a route pattern, but no matter how hard I search, I can't find anything about this at all in any Microsoft documentation, and none of the blog posts I've found explain what it's doing or mention where that bit of information came from.
Where is this constrained explained, and where is the comprehensive, up-to-date, canonical documentation for built-in route patterns and constraints? For the record, I am aware of this page, but it's structured more like a tutorial than a canonical reference.
If anyone from Microsoft is reading this, http://www.asp.net/mvc/overview/api-reference leads to a page with next to no information and an unsynced table of contents that I can't find what I want within. And your RouteAttribute class reference has no links to anything explaining what a url pattern should look like.
EDIT
So after some deeper digging, I found this:
https://github.com/aspnet/Mvc/blob/48bfdceea6d243c5ec8d6e00f450f8fe7cce59f7/src/Microsoft.AspNet.Mvc.Core/MvcCoreRouteOptionsSetup.cs#L26
So it's related to KnownRouteValueConstraint, which led me to this:
https://github.com/aspnet/Mvc/blob/e0b8532735997c439e11fff68dd342d5af59f05f/src/Microsoft.AspNet.Mvc.Core/KnownRouteValueConstraint.cs#L26-L40
So I guess that means the constraint simply makes sure the captured value is non-null. I still don't know where the canonical source for that information is though.
Since ASP.NET 5/MVC 6 is not yet officially released and at the moment the API is not yet stable, it isn't that surprising that the documentation has not been completed yet.
Do note that ASP.NET vNext is open source, so where documentation is lacking you can always look at tests to try to work out what to do. Here are some that test the inline constraint area:exists.
[Fact]
public async Task RoutingToANonExistantArea_WithExistConstraint_RoutesToCorrectAction()
{
// Arrange
var server = TestHelper.CreateServer(_app, SiteName, _configureServices);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/area-exists/Users");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var returnValue = await response.Content.ReadAsStringAsync();
Assert.Equal("Users.Index", returnValue);
}
[Fact]
public async Task RoutingToANonExistantArea_WithoutExistConstraint_RoutesToIncorrectAction()
{
// Arrange
var server = TestHelper.CreateServer(_app, SiteName, _configureServices);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/area-withoutexists/Users");
// Assert
var exception = response.GetServerException();
Assert.Equal("The view 'Index' was not found." +
" The following locations were searched:__/Areas/Users/Views/Home/Index.cshtml__" +
"/Areas/Users/Views/Shared/Index.cshtml__/Views/Shared/Index.cshtml.",
exception.ExceptionMessage);
}
I'm in the middle of a significant effort to introduce NHibernate into our code base. I figured I would have to use some kind of a DI container, so I can inject dependencies into the entities I load from the database. I chose Unity as that container.
I'm considering using Unity's interception mechanism to add a transaction aspect to my code, so I can do e.g. the following:
class SomeService
{
[Transaction]
public void DoSomething(CustomerId id)
{
Customer c = CustomerRepository.LoadCustomer(id);
c.DoSomething();
}
}
and the [Transaction] handler will take care of creating a session and a transaction, committing the transaction (or rolling back on exception), etc.
I'm concerned that using this kind of interception will bind me to using Unity pretty much everywhere in the code. If I introduce aspects in this manner, then I must never, ever call new SomeService(), or I will get a service that doesn't have transactions. While this is acceptable in production code, it seems too much overhead in tests. For example, I would have to convert this:
void TestMethod()
{
MockDependency dependency = new MockDependency();
dependency.SetupForTest();
var service = SomeService(dependency);
service.DoSomething();
}
into this:
void TestMethod()
{
unityContainer.RegisterType<MockDependency>();
unityContainer.RegisterType<IDependency, MockDependency>();
MockDependency dependency = unityContainer.Resolve<MockDependency>();
dependency.SetupForTest();
var service = unityContainer.Resolve<SomeService>();
service.DoSomething();
}
This adds 2 lines for each mock object that I'm using, which leads to quite a bit of code (our tests use a lot of stateful mocks, so it is not uncommon for a test class to have 5-8 mock objects, and sometimes more.)
I don't think standalone injection would help here: I have to set up injection for every class that I use in the tests, because it's possible for aspects to be added to a class after the test is written.
Now, if I drop the use of interception I'll end up with:
class SomeService
{
public void DoSomething(CustomerId id)
{
Transaction.Run(
() => {
Customer c = CustomerRepository.LoadCustomer(id);
c.DoSomething();
});
}
}
which is admittedly not as nice, but doesn't seem that bad either.
I can even set up my own poor man's interception:
class SomeService
{
[Transaction]
public void DoSomething(CustomerId id)
{
Interceptor.Intercept(
MethodInfo.GetCurrentMethod(),
() => {
Customer c = CustomerRepository.LoadCustomer(id);
c.DoSomething();
});
}
}
and then my interceptor can process the attributes for the class, but I can still instantiate the class using new and not worry about losing functionality.
Is there a better way of using Unity interception, that doesn't force me to always use it for instantiating my objects?
If you want to use AOP but are concerned abut Unity then I would recommend you check out PostSharp. That implements AOP as a post-compile check but has no changes on how you use the code at runtime.
http://www.sharpcrafters.com/
They have a free community edition that has a good feature set, as well as professional and enterprise versions that have significantly enhanced feature sets.
I’m about to start work on an OpenRasta project (an xml over http web service). OpenRasta looks great but unfortunately worked examples seem few and far between on the internet. Looking at the test side of the project, if my handlers are returning strongly typed objects (not OperationResult), i.e.:
public class PersonHandler
...
public Person Get(int id)
{
...
How can I test for http status codes? (For example if the handler throws an uncaught exception). I’m not sure what level the tests pitch in at, and what needs mocking (using moq btw)
Any help appreciated, particularly coded examples!
I faced the same problem, and ended up writing my tests as integration tests at a much higher level, actually making real REST/HTTP calls through a simple HttpWebRequest client. This allowed me to check the HTTP response headers / status codes and double-check the JSON/XML serialization from the client's perspective, which was just as important as whether or not the operations succeeded.
I started by returning OperationResult from all my handlers, and used these to wrap the strongly-typed objects. My handlers all inherit from a base class with a few helper methods that make it easier to return a custom error with a user-friendly error message. The more I coded this up, the more my handlers resembled a ASP.NET MVC controller. e.g.:
public OperationResult GetById(int id)
{
try
{
// do stuff here
return OKResult( // some strongly-typed resource );
}
catch(SomeException ex)
{
return BadRequestResult(SomeErrorCode, ex.Message);
}
}
Then in the test client, it's pretty easy to just check the HTTP status code. Obviously this doesn't help much with mocking. I'm not sure what the best solution is, in fact I've favorited this question in the hope that someone answers it better than I can - but this has worked pretty well for me so far.
The handler is just a class--ideally with minimal dependencies--so your unit tests can just test the isolated logic in the class.
If you want to test for status codes, I recommend (based on very little experience!) using OpenRasta self-hosting.
Here's a test (somewhat changed) that I wrote recently:
[TestMethod]
public void POST_with_inaccurate_contentLength_returns_405()
{
var resource = GetResource();
IRequest request = new InMemoryRequest
{
HttpMethod = "POST",
Uri = new Uri("http://localhost/Resource"),
};
request.Headers.ContentLength = 16; //wrong!
request.Entity.Stream.Write(resource.Content, 0, resource.Content.Length);
var response = _host.ProcessRequest(request);
Assert.AreEqual(405, response.StatusCode);
}
I should add that the host is set up in the TestInitialize method as such:
_host = new InMemoryHost(new Configuration());
_host.Resolver.AddDependencyInstance(typeof(IFileResourceRepository), _repository, DependencyLifetime.Singleton);
...and is cleaned up in the TestCleanup method.