Could not create an instance of type ITask. Type is an interface or abstract class and cannot be instantiated - json.net

I have the class structure:
public class Task1 : ITask
and
public class Task2 : ITask
and some method:
public static T FromByteArray<T>(byte[] data)
{
if (data == null)
return default(T);
using (var stream = new MemoryStream(data))
using (var reader = new StreamReader(stream, Encoding.UTF8))
return (T)JsonSerializer.Create().Deserialize(reader, typeof(T));
}
where I pass the interface. And get the error:
"Could not create an instance of type ITask. Type is an interface or abstract class and cannot be instantiated."
I read similar questions, but how can I use the solution with the JsonSerializerSettings in my case?
In my case method Deserialize do not have an option for JsonSerializerSettings

Related

How to Implement beanprocessor to examine the attribute of meta listener?

My meta listener code
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
#KafkaListener(containerFactory = "myListenerContainerFactory", autoStartup = "false")
public #interface mylistener1 {
#AliasFor(annotation = KafkaListener.class, attribute = "topics")
String[] topics();
String myattr() default "";
}
Consume method:
#Service
Class ConsumerService(){
#mylistener1(topics = "new.topic",myattr="new.myatr.topic")
public void consume(String message) {
LOG.info("consumer-> " + message);
}
}
I tried to get value from ApplicationContext, but it was not getting the listener.
#Autowired
ApplicationContext ctx;
Map<String, Object> allBeansWithNames = ctx.getBeansWithAnnotation(mylistener1.class);
allBeansWithNames - 0, and I am not getting class list which is having #mylistener1 annotation`your text`
I want to implement beanpostprocessor to check myattr at runtime and use it to send message`
getBeansWithAnnotation() will only find beans with classes that are so annotated (or #Bean factory methods). It doesn't look at the class methods.
Take a look at KafkaListenerAnnotationBeanPostProcessor for an example of a BPP that examines annotations and their attributes.

How do I test a Signal R hub that has LifetimeScope injected into it

How can I write unit tests to test my hub?
Here is my Hub Class:
public class MyHub : Hub
{
private readonly ILifetimeScope _scope;
private readonly IMyProvider _provider;
public MyHub(ILifetimeScope scope)
{
scope = _scope;
_provider = _scope.Resolve<IMyProvider>();
}
public void BroadcastMessage(int messageId)
{
var myMessage = _provider.GetFromDb(messageId);
Clients.All.broadcastMessage(myMessage);
}
}
I'm using moq and xunit, i've tried things like this:
//arrange
var messageId = 1;
var message = "test";
var providerMock = new Mock<IMyProvider>();
providerMock.Setup(x => x.GetFromDb(messageId).Returns(test);
var scopeMock = new Mock<ILifetimeScope>();
scopeMock.Setup(x => x.Resolve<IMyProvider>()).Returns(providerMock.Object);
var hub = new MyHub(scopeMock.Object);
//act
hub.BroadcastMessage(messageId);
//assert
providerMock.Verify(x => x.GetFromDb(messageId), Times.Once());
but this causes an error:
System.NotSupportedException : Unsupported expression: x => x.Resolve()
Extension methods (here: ResolutionExtensions.Resolve) may not be used in setup / verification expressions.
I found this answer: https://stackoverflow.com/a/49523868/3708225 that says I can do something like
using (var mock = AutoMock.GetLoose()){
var providerMock = new Mock<IMyPRovider>();
providerMock.Setup(x=>x.GetFromDb(messageId)).Returns(message);
mock.Provide(providerMock.Object);
var lifetime = mock.Create<ILifetimeScope>();
using (var scope = lifetimeScope.BeginLifetimeScope()){
var innerMockProvider = scope.Resolve<IMyProvider>();
//rest of test
}
}
but AutoMock.GetLoose().Provide() isn't defined
This is probably not the answer you are looking for. But a workaround would be not to mock lifetimescope but simply setup a autofac container to use in these tests.
Secondly do you need to inject the lifetimescope directly in your class? Maybe use a decorator pattern where you let the decorator create the lifetimescope and resolve your class and invoke it. Getting rid of the lifetimescope in your myhub class will make your life easier. Make it the job of some other class to control the lifetimescope. Else you will need to repeat this pattern in all your other classes as well. You should instead inject IMyProvider.
This is how I solved this:
If I change my hub to the following:
public class MyHub : Hub
{
private readonly <Func>IMyProvider _provider;
public MyHub(<Func>IMyProvider provider)
{
_provider = provider;
}
public void BroadcastMessage(int messageId)
{
var provider = _provider();
var myMessage = provider.GetFromDb(messageId);
Clients.All.broadcastMessage(myMessage);
}
}
Now i can mock Func<IMyProviider> to return what I need and ignore the lifetime scope

ASP.NET Core ControllerContext vs ActionContext in UrlHelper

I am trying to implement pagination in my Asp.net core 2 API. To create pagination links, I am using UrlHelper. The constructor for UrlHelper requires the context in which the action runs.
The examples I've seen have been using below configuration in startup and then injecting IUrlHelper into the controller where it is needed.
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
services.AddScoped<IUrlHelper>(x => {
var actionContext = x.GetRequiredService<IActionContextAccessor>().ActionContext;
var factory = x.GetRequiredService<IUrlHelperFactory>();
return factory.GetUrlHelper(actionContext);
});
But controllers also have ControllerContext which derives from ActionContext (https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.controllercontext?view=aspnetcore-2.1).
I am able to do the following:
public Object GetAll() //ignore object return, for test purposes
{
var urlHelper = new UrlHelper(ControllerContext);
var nextLink = urlHelper.Link("GetPosts", new { page = 1, pageSize = 3 });
//return _context.Posts;
return new
{
NextPageLink = nextLink,
Results = _context.Posts,
test = ControllerContext.RouteData.Values
};
}
The code above is able to create the links correctly. I don't have a firm grasp on the nuances of the framework so I am wondering if above is a correct way to initialize UrlHelper. Will this lead to problems? If you can point me in the direction of some documentation around this or explain the reason behind if the approach is good/bad, that would be very helpful.
What you have can work.
It does however tightly couple the controller to an implementation concern.
If you have need for the helper you can follow a similar format to what was configured at startup by injecting the IUrlHelperFactory into the controller and getting the helper using the controller's ControllerContext, which as you have already discovered, derives from ActionContext
public class MyController : Controller {
private readonly IUrlHelperFactory factory;
//...other dependencies
public MyController(IUrlHelperFactory factory) {
this.factory = factory;
//...other dependencies
}
public IActionResult GetAll() {
var urlHelper = factory.GetUrlHelper(ControllerContext);
var nextLink = urlHelper.Link("GetPosts", new { page = 1, pageSize = 3 });
return Ok(new {
NextPageLink = nextLink,
Results = _context.Posts,
test = ControllerContext.RouteData.Values
});
}
//...other actions
}

Testing Spring's #RequestBody using Spring MockMVC

I am trying to test a method that posts an object to the database using Spring's MockMVC framework. I've constructed the test as follows:
#Test
public void testInsertObject() throws Exception {
String url = BASE_URL + "/object";
ObjectBean anObject = new ObjectBean();
anObject.setObjectId("33");
anObject.setUserId("4268321");
//... more
Gson gson = new Gson();
String json = gson.toJson(anObject);
MvcResult result = this.mockMvc.perform(
post(url)
.contentType(MediaType.APPLICATION_JSON)
.content(json))
.andExpect(status().isOk())
.andReturn();
}
The method I'm testing uses Spring's #RequestBody to receive the ObjectBean, but the test always returns a 400 error.
#ResponseBody
#RequestMapping( consumes="application/json",
produces="application/json",
method=RequestMethod.POST,
value="/object")
public ObjectResponse insertObject(#RequestBody ObjectBean bean){
this.photonetService.insertObject(bean);
ObjectResponse response = new ObjectResponse();
response.setObject(bean);
return response;
}
The json created by gson in the test:
{
"objectId":"33",
"userId":"4268321",
//... many more
}
The ObjectBean class
public class ObjectBean {
private String objectId;
private String userId;
//... many more
public String getObjectId() {
return objectId;
}
public void setObjectId(String objectId) {
this.objectId = objectId;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
//... many more
}
So my question is: how to I test this method using Spring MockMVC?
Use this one
public static final MediaType APPLICATION_JSON_UTF8 = new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8"));
#Test
public void testInsertObject() throws Exception {
String url = BASE_URL + "/object";
ObjectBean anObject = new ObjectBean();
anObject.setObjectId("33");
anObject.setUserId("4268321");
//... more
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, false);
ObjectWriter ow = mapper.writer().withDefaultPrettyPrinter();
String requestJson=ow.writeValueAsString(anObject );
mockMvc.perform(post(url).contentType(APPLICATION_JSON_UTF8)
.content(requestJson))
.andExpect(status().isOk());
}
As described in the comments, this works because the object is converted to json and passed as the request body. Additionally, the contentType is defined as Json (APPLICATION_JSON_UTF8).
More info on the HTTP request body structure
the following works for me,
mockMvc.perform(
MockMvcRequestBuilders.post("/api/test/url")
.contentType(MediaType.APPLICATION_JSON)
.content(asJsonString(createItemForm)))
.andExpect(status().isCreated());
public static String asJsonString(final Object obj) {
try {
return new ObjectMapper().writeValueAsString(obj);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
The issue is that you are serializing your bean with a custom Gson object while the application is attempting to deserialize your JSON with a Jackson ObjectMapper (within MappingJackson2HttpMessageConverter).
If you open up your server logs, you should see something like
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not construct instance of java.util.Date from String value '2013-34-10-10:34:31': not a valid representation (error: Failed to parse Date value '2013-34-10-10:34:31': Can not parse date "2013-34-10-10:34:31": not compatible with any of standard forms ("yyyy-MM-dd'T'HH:mm:ss.SSSZ", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "EEE, dd MMM yyyy HH:mm:ss zzz", "yyyy-MM-dd"))
at [Source: java.io.StringReader#baea1ed; line: 1, column: 20] (through reference chain: com.spring.Bean["publicationDate"])
among other stack traces.
One solution is to set your Gson date format to one of the above (in the stacktrace).
The alternative is to register your own MappingJackson2HttpMessageConverter by configuring your own ObjectMapper to have the same date format as your Gson.
I have encountered a similar problem with a more recent version of Spring. I tried to use a new ObjectMapper().writeValueAsString(...) but it would not work in my case.
I actually had a String in a JSON format, but I feel like it is literally transforming the toString() method of every field into JSON. In my case, a date LocalDate field would end up as:
"date":{"year":2021,"month":"JANUARY","monthValue":1,"dayOfMonth":1,"chronology":{"id":"ISO","calendarType":"iso8601"},"dayOfWeek":"FRIDAY","leapYear":false,"dayOfYear":1,"era":"CE"}
which is not the best date format to send in a request ...
In the end, the simplest solution in my case is to use the Spring ObjectMapper. Its behaviour is better since it uses Jackson to build your JSON with complex types.
#Autowired
private ObjectMapper objectMapper;
and I simply used it in my test:
mockMvc.perform(post("/api/")
.content(objectMapper.writeValueAsString(...))
.contentType(MediaType.APPLICATION_JSON)
);

How to unit test an UrlHelper custom helper method

I am using ASP.NET MVC 3 and NUnit. I am trying to write a unit to test one of my helper methods. Here it is:
public static class UrlHelperAssetExtensions
{
private static readonly string yuiBuildPath = "http://yui.yahooapis.com/2.8.2r1/build/";
public static string YuiResetFontsGridsStylesheet(this UrlHelper helper)
{
return helper.Content(yuiBuildPath + "reset-fonts-grids/reset-fonts-grids.css");
}
}
Here is my unit test:
[Test]
public void YuiResetFontsGridsStylesheet_should_return_stylesheet()
{
// Arrange
RequestContext requestContext = new RequestContext();
UrlHelper urlHelper = new UrlHelper(requestContext);
// Act
string actual = urlHelper.YuiResetFontsGridsStylesheet();
// Assert
string expected = yuiBuildPath + "reset-fonts-grids/reset-fonts-grids.css";
Assert.AreEqual(expected, actual);
}
Am I testing it the correct way? When I run it in the NUnit GUI then I get the following error:
System.ArgumentNullException : Value cannot be null.
Parameter name: httpContext
Is this possible to test? If so please explain in clear how do I get an instance of httpContext?
UPDATED
I can't get this test to pass. In my method I have the following:
private static readonly string stylesheetPath = "~/Assets/Stylesheets/";
public static string Stylesheet(this UrlHelper helper)
{
return helper.Content(stylesheetPath + "MyStylesheet.css");
}
The test that I wrote for it is the following:
private string stylesheetPath = "/Assets/Stylesheets/";
private HttpContextBase httpContextBaseStub;
private RequestContext requestContext;
private UrlHelper urlHelper;
[SetUp]
public void SetUp()
{
httpContextBaseStub = MockRepository.GenerateStub<HttpContextBase>();
requestContext = new RequestContext(httpContextBaseStub, new RouteData());
urlHelper = new UrlHelper(requestContext);
}
[Test]
public void Stylesheet_should_return_stylesheet()
{
// Act
string actual = urlHelper.Stylesheet();
// Assert
string expected = stylesheetPath + "MyStylesheet.css";
Assert.AreEqual(expected, actual);
}
The NUnit GUI gives the following error:
System.NullReferenceException : Object reference not set to an instance of an object.
It seems to be getting the error with the ~ in:
private static readonly string stylesheetPath = "~/Assets/Stylesheets/";
You need to mock HttpContext. Here's the example using Moq:
// Arrange
var context = new Mock<HttpContextBase>();
RequestContext requestContext = new RequestContext(context.Object, new RouteData());
UrlHelper urlHelper = new UrlHelper(requestContext);
If you do not want to use a mocking framework, you can create a class that will derive from HttpContextBase and use it instead. But this will require implementing a lot of abstract members, which you can avoid by mocking it.
Personally I like using MVCContrib TestHelper:
// arrange
// TODO: You could move this part in the SetUp part of your unit test
// to avoid repeating it in all tests
var cb = new TestControllerBuilder();
cb
.HttpContext
.Response
.Stub(x => x.ApplyAppPathModifier(Arg<string>.Is.Anything))
.WhenCalled(mi =>
{
mi.ReturnValue = mi.Arguments[0];
})
.Return(null);
var rc = new RequestContext(cb.HttpContext, new RouteData());
var helper = new UrlHelper(rc);
// act
var actual = helper.Stylesheet();
// assert
Assert.AreEqual("/Assets/Stylesheets/MyStylesheet.css", actual);

Resources