Why does .net MVC source code ControllerBuilder use a delegate to assign the controller factory?:
private Func<IControllerFactory> _factoryThunk;
public void SetControllerFactory(IControllerFactory controllerFactory) {
_factoryThunk = () => controllerFactory;
}
Why can't it just assign the ControllerFactory directly?, ie:
private IControllerFactory _factory;
public void SetControllerFactory(IControllerFactory controllerFactory) {
_factory = controllerFactory;
}
public void SetControllerFactory(Type controllerFactoryType) {
_factory = (IControllerFactory)Activator.CreateInstance(controllerFactoryType);
}
The reason that _factoryThunk is currently defined as a Func<IControllerFactory> is that it's a generic means to support both overloads:
void SetControllerFactory(Type);
void SetControllerFactory(IControllerFactory);
The implementation of the first one uses the fact that _factoryThunk is a Func by declaring that Func inline by using Activator to instantiate the Type lazily:
this._factoryThunk = delegate {
IControllerFactory factory;
try
{
factory = (IControllerFactory) Activator.CreateInstance(controllerFactoryType);
}
catch (Exception exception)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, MvcResources.ControllerBuilder_ErrorCreatingControllerFactory, new object[] { controllerFactoryType }), exception);
}
return factory;
};
Therefore, the reason the other overload looks like it has a spurious implementation is that since _factoryThunk is declared as a Func, the line you propose wouldn't have even compiled:
_factoryThunk = controllerFactory;
_factoryThunk is a Func<IControllerFactory> whereas controllerFactory is an IControllerFactory -- incompatible types.
Related
I m trying create unit tests for one project.I m facing a problem because when I try control the result of an interface(mock). When the code get the Interface variable that return a NullPointerException.
Firstly I tried #Override the method in my test class (ClassA), but it don't work. After that I tried mock the interface object and control the comportment with Mockito.When().tehnReturn();
I will put here my code, I read some solutions but none works.
My Interface:
#FunctionalInterface
public interface Interface {
UpdateXResponse process(UpdateXRequest request) throws Exception;
}
The class I want to test:
#Service(ClassA.class)
public class ClassA extends VService implements UpdateX {
#Reference
#Inject
private Interface interface;
#Inject
public ClassA(...) {...}
#Override
public UpdateXResponse process(UpdateXRequest request) throws Exception {
UpdateXResponse response = initResponse(context, request, new UpdateXResponse());
UpdateXInput input = request.getInput();
UpdateXOutput output = new UpdateXOutput();
response.setOutput(output);
try {
firstMethodCall(...);
} catch (Exception t) {
throwCorrectException(t, logger);
}
return response;
}
private void firstMethodCall(...) throws Exception {
TypeF typeF = callInterfaceMethod(...);
...
}
/**
* Orchestrates Interface service
*/
protected TypeF callInterfaceMethod(...) {
...
request.setInput(input);
request.setHeader(header);
InterfaceResponse response = interface.process(request); // LINE ERROR - In this step interface is NULL when the test get this
return response;
}
}
And finally my class test:
#RunWith(PowerMockRunner.class)
#PrepareForTest(value = {ClassA.class,Interface.class} )
public class WithPowerMockUnitTest{
#InjectMocks
private ClassA classA;
private Interface interface;
#Before
public void setUp() throws Exception {
InterfaceRequest InterfaceRequest = createInterfaceRequest();
InterfaceResponse serviceUnavailableResponse = createInterfaceResponse();
Interface = Mockito.mock(Interface.class);
when(Interface.process(Mockito.any(InterfaceRequest.class))).thenReturn(serviceUnavailableResponse);
}
#Test
public void testh() throws SOAException {
InterfaceResponse res = interface.process(Mockito.any(InterfaceRequest.class)); // There all run ok. The interface is not null and return what i expected.
System.out.println("RES "+res);
}
#Test
public void test() {
assertNotNull(classA); // not null
assertNotNull(interface); // not null
}
#Test
public void newTest() throws Exception {
InterfaceRequest InterfaceRequest = createInterfaceRequest();
InterfaceResponse serviceUnavailableResponse = createInterfaceResponse();
UpdateXResponse response = ClassA.process(updateXRequest()); // PROBLEM!! When that get the LINE ERROR the interface is null! WHY?
}
}
I put some comments in the lines where the problem exists for me.
public interface A{
Response process(Request r) throws Exception;
}
public class B{
private Class_That_Override_Interface_method ctoim;
public Response function(){
X res = method_B();
}
protected X method_B(){
response res = ctoim.process(request); // That ctoim is always NULL when the test get that line/call
}
}
Thanks
You're missing the #Mock annotation on your Interface variable.
Therefore the mock is not injected into your classA and the newTest() fails. (In this case remove Interface = Mockito.mock(Interface.class); from the setUp method).
Alternativly remove the #InjectMocks annotation and create your class under test manually passing your mock into the constructor.
For this specific case (assuming its a different case from the last question)
there doesn't seem to be a need to involve PowerMockito. So unless you left out some relevant parts you might as well just use the MockitoJUnitRunner.
Ps.:
Also remeber what I said last time about compilable examples?
interface is a keyword and can't be used for variables.
You should also aim to write variables identical all the times (not Interface and interface / classA and ClassA)
And in case you haven't read it yet check out the help section about minmal reproducible examples.
Edit:
I fogot to mention that the line interface.process(Mockito.any(InterfaceRequest.class)); in testh() is actually invalid syntax. You should use ArgumentMatchers only for parameters of mocked methods.
Also consider adding the MockitoAnnotations.initMocks(this); to your setUp method, when using the PowerMockRunner.
First the error:
Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and
then later trying to use the same context instance elsewhere in your
application. This may occur if you are calling Dispose() on the
context, or wrapping the context in a using statement. If you are
using dependency injection, you should let the dependency injection
container take care of disposing context instances.
Object name: 'MemberContext'.
I have 3 projects, Domain, API and WebSPA app.
Domain has 2 modules, DomainModule and MediatorModule
public class DomainModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(typeof(MemberContext).Assembly)
.AsImplementedInterfaces()
.InstancePerLifetimeScope(); // via assembly scan
builder.RegisterType<MemberContext>().AsSelf()
.InstancePerLifetimeScope(); // or individually
}
}
public class MediatorModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
// enables contravariant Resolve() for interfaces with single contravariant ("in") arg
builder
.RegisterSource(new ContravariantRegistrationSource());
// mediator itself
builder
.RegisterType<Mediator>()
.As<IMediator>()
.InstancePerLifetimeScope();
// request handlers
builder
.Register<SingleInstanceFactory>(ctx =>
{
var c = ctx.Resolve<IComponentContext>();
return t =>
{
object o;
return c.TryResolve(t, out o) ? o : null;
};
})
.InstancePerLifetimeScope();
// notification handlers
builder
.Register<MultiInstanceFactory>(ctx =>
{
var c = ctx.Resolve<IComponentContext>();
return t => (IEnumerable<object>) c.Resolve(typeof(IEnumerable<>).MakeGenericType(t));
})
.InstancePerLifetimeScope();
}
}
In API project I have also 2 modules, ApplicationModule and again MediatorModule same as the one above.
public class ApplicationModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(typeof(Startup).Assembly)
.AsImplementedInterfaces()
.InstancePerLifetimeScope(); // via assembly scan
builder.RegisterType<MemberContext>().AsSelf().InstancePerLifetimeScope(); // or individually
}
}
No, when I debug I can see that member context gets newed up on each request, yet on second request, it throws above error. To make sure I am not going crazy, I modified constructor of dbcontext to create an id for context so i can verify they are different. What am I doing wrong?
public MemberContext(DbContextOptions<MemberContext> options) : base(options)
{
MemberContextId = Guid.NewGuid();
Console.WriteLine("member context created: " + MemberContextId);
}
Here is the startup in API
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
// .AllowCredentials()
);
});
services.AddMvc()
.AddControllersAsServices();//Injecting Controllers themselves thru DI
//For further info see: http://docs.autofac.org/en/latest/integration/aspnetcore.html#controllers-as-services
AddSwaggerGen(services);
//var connection = Configuration["ConnectionString"];
//services.AddDbContext<MemberContext>(options => options.UseSqlServer(connection),ServiceLifetime.Scoped);
services.AddEntityFrameworkSqlServer()
.AddDbContext<MemberContext>(options =>
{
options.UseSqlServer(Configuration["ConnectionString"]
//,sqlServerOptionsAction: sqlOptions =>
//{
// sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
// sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
//}
);
},
ServiceLifetime.Scoped //Showing explicitly that the DbContext is shared across the HTTP request scope (graph of objects started in the HTTP request)
);
var container = new ContainerBuilder();
container.Populate(services);
container.RegisterAssemblyModules(typeof(VIN.Members.Domain.Entities.Member).Assembly,
typeof(Startup).Assembly);
return new AutofacServiceProvider(container.Build());
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
//NOTE: must be before UseMVC !!!
app.UseCors("CorsPolicy");
app.UseMvc();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});
}
private void AddSwaggerGen(IServiceCollection services)
{
services.AddSwaggerGen(options =>
{
options.DescribeAllEnumsAsStrings();
options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info
{
Title = "VIN Members HTTP API",
Version = "v1",
Description = "Members Service HTTP API",
TermsOfService = "Terms Of Service"
});
});
}
}
UPDATE:
What I am trying to do is delete a record. On client side code looks like this
onDelete(item: IMember) {
//TODO: replace this with dialog service component
if (window.confirm('Are sure you want to delete this member?')) {
//put your delete method logic here
this.service.deleteMember(item).subscribe(x => {
this.getMembers();
});
}
}
this delete request gets mapped to a controller that passes it to mediator
Controller
// DELETE api/members/5
[HttpDelete("{id}")]
public void Delete(Guid id)
{
var command = new DeleteMember.Command(id);
_mediator.Send(command).ConfigureAwait(false);
}
and finally handler
public class DeleteMember
{
public class Command : IRequest
{
public Command(Guid memberId)
{
Guard.NotNull(memberId, nameof(memberId));
MemberId = memberId;
}
public Guid MemberId { get; }
}
public class Handler : AsyncRequestHandler<Command>
{
private MemberContext _context;
public Handler(MemberContext context)
{
_context = context;
Console.WriteLine("Delete member context: " + context.MemberContextId);
}
protected override async Task HandleCore(Command cmd)
{
try
{
var member = await _context.FindAsync<Member>(cmd.MemberId);//.ConfigureAwait(false);
// if (member != null)
//// {
_context.Remove(member);
await _context.SaveChangesAsync().ConfigureAwait(false);
// }
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
}
}
As you can see there is no code that disposes that context. Scratching my head.
See this commented out check for member if null. That was throwing error as well, I commented it out just to see what will happen, and now it throws as SaveChangesAsync.
As request completes, context gets disposed. Since command handler uses SaveChangesAsync(), context is disposed before save completes. Culprit is controller method :). It should be async as well.
[HttpDelete("{id}")]
public async Task Delete(Guid id)
{
var command = new DeleteMember.Command(id);
await _mediator.Send(command).ConfigureAwait(false);
}
Your DbContext is scoped, meaning that Dependency Injection will return the same DbContext object every time one is asked for within the same HTTP request (in the case of ASP.NET).
That means that you should not be calling Dispose on your DbContext (otherwise that same object can't be used a second time). That seems to be what is happening to you, intentionally or not.
That does mean you should not be using using with it. Are you using using anywhere in your code against your DbContext?
I don't think you showed the line where the Exception is being thrown.
Update:
Try overriding Dispose in your MemberContext class. Something like this:
public override void Dispose() {
base.Dispose();
}
But just set a breakpoint there. When it breaks (if it does) check the stack trace and see what called it.
This can also be caused by having async void instead of async Task within WebAPI in my experience.
I want to mock a Class in Mockito. It will then have a .newInstance() call issued which will be expected to return an actual class instance (and will return a mock in my case).
If it was setup correctly then I could do:
ArrayList myListMock = mock(ArrayList.class);
when(myVar.newInstance()).thenReturn(myListMock);
I know I can set it up so that a new instance of class ArrayList will be a mock (using PowerMockito whenNew), just wondering if there was a way to mock this kind of a class object so I don't have to override instance creation...
Below is the real class I'm trying to mock, I can't change the structure it is defined by the interface. What I'm looking for is a way to provide cvs when initialize is called.
public class InputConstraintValidator
implements ConstraintValidator<InputValidation, StringWrapper> {
Class<? extends SafeString> cvs;
public void initialize(InputValidation constraintAnnotation) {
cvs = constraintAnnotation.inputValidator();
}
public boolean isValid(StringWrapper value,
ConstraintValidatorContext context) {
SafeString instance;
try {
instance = cvs.newInstance();
} catch (InstantiationException e) {
return false;
} catch (IllegalAccessException e) {
return false;
}
}
Mockito is designed exclusively for mocking instances of objects. Under the hood, the mock method actually creates a proxy that receives calls to all non-final methods, and logs and stubs those calls as needed. There's no good way to use Mockito to replace a function on the Class object itself. This leaves you with a few options:
I don't have experience with PowerMock but it seems it's designed for mocking static methods.
In dependency-injection style, make your static factory method into a factory instance. Since it looks like you're not actually working with ArrayList, let's say your class is FooBar instead:
class FooBar {
static class Factory {
static FooBar instance;
FooBar getInstance() {
if (instance == null) {
instance = new FooBar();
}
return instance;
}
}
// ...
}
Now your class user can receive a new FooBar.Factory() parameter, which creates your real FooBar in singleton style (hopefully better and more threadsafe than my simple implementation), and you can use pure Mockito to mock the Factory. If this looks like it's a lot of boilerplate, it's because it is, but if you are thinking of switching to a DI solution like Guice you can cut down a lot of it.
Consider making a field or method package-private or protected and documenting that it's visible for testing purposes. Then you can insert a mocked instance in test code only.
public class InputConstraintValidator implements
ConstraintValidator<InputValidation, StringWrapper> {
Class<? extends SafeString> cvs;
public void initialize(InputValidation constraintAnnotation) {
cvs = constraintAnnotation.inputValidator();
}
public boolean isValid(StringWrapper value,
ConstraintValidatorContext context) {
SafeString instance;
try {
instance = getCvsInstance();
} catch (InstantiationException e) {
return false;
} catch (IllegalAccessException e) {
return false;
}
}
#VisibleForTesting protected getCvsInstance()
throws InstantiationException, IllegalAccessException {
return cvs.newInstance();
}
}
public class InputConstaintValidatorTest {
#Test public void testWithMockCvs() {
final SafeString cvs = mock(SafeString.class);
InputConstraintValidator validator = new InputConstraintValidator() {
#Override protected getCvsInstance() {
return cvs;
}
}
// test
}
}
I think you just need to introduce an additional mock for Class:
ArrayList<?> myListMock = mock(ArrayList.class);
Class<ArrayList> clazz = mock(Class.class);
when(clazz.newInstance()).thenReturn(myListMock);
Of course the trick is making sure your mocked clazz.newInstance() doesn't end up getting called all over the place because due to type-erasure you can't specify that it's actually a Class<ArrayList>.
Also, be careful defining your own mock for something as fundamental as ArrayList - generally I'd use a "real one" and populate it with mocks.
public class Temp
{
List<T> values = new List<T>;
static Temp()
{
System.Console.WriteLine("static constructor");
}
public Temp()
{
System.Console.WriteLine("general constructor");
}
}
Also please explain me when will the List object will be created and with what type it is created.
}
It appears the field gets initialized first, then the static constructor is called, then the constructor.
class Test
{
string variable = new Func<string>(() =>
{
Console.WriteLine("field initializer");
return "VARIABLE";
})();
static string staticvariable = new Func<string>(() =>
{
Console.WriteLine("static field initializer");
return "STATICVARIABLE";
})();
static Test()
{
System.Console.WriteLine("static constructor");
}
public Test()
{
System.Console.WriteLine("general constructor");
}
}
Test t = new Test();
outuput:
static field initializer
static constructor
field initializer
general constructor
[edit]
Oops sorry, it was a non-static field and I didn't notice it.
The static ctor will be called first.
Then values list will be second and the the ctor.
Read about beforefieldinit here.
I am trying to refactor some of my code to use Func
I have created a sample to try to understand how it works but I am getting compilation error. In the e.g. below when I am trying to access the parameter attributes or return the return value the compiler complain.
Clarifications please.
using System;
namespace chsarp
{
class Program
{
static void Main(string[] args)
{
ParamInput input = new ParamInput();
input.ReservationID = 10;
Test testMethod = new Test();
Func<ParamInput, ReservationResult> methodToInvoke = testMethod.GetStatus;
ReservationResult result = TestFn(methodToInvoke, input);
}
static Result TestFn<Param, Result>(Func<Param, Result> methodToInvoke, Param parameter) where Result : new()
{
Result result = new Result();
try
{
result = methodToInvoke(parameter);
}
catch (Exception exception)
{
result.status = string.Format("Error-{0} during reserving {1}",
parameter.ReservationID,
exception.Message);
}
return result;
}
}
class Test
{
public ReservationResult GetStatus(ParamInput msg)
{
ReservationResult result = new ReservationResult();
result.status = string.Format("The ReservationID-{0}", msg.ReservationID);
return result;
}
}
class ParamInput
{
public int ReservationID { get; set; }
}
class ReservationResult
{
public string status { get; set; }
}
}
Annotated compile errors:
error CS1061: 'Result' does not contain a definition for 'status'
error CS1061: 'Param' does not contain a definition for 'ReservationID'
Code using generic type arguments can only compile if the compiler knows the member of the generic type. It doesn't know that the Result type argument has a "status" member. It certainly doesn't if you invoke TestFn<object, object>().
You'll need to use a constraint to make this work. You already do, but new() isn't strong enough. Something like "where Result : IResult" for example, where IResult is an interface type that has a status property. Or a base class. The compiler can now be 100% sure that any allowed concrete instance of the generic method will execute without causing runtime errors. Since it can only ever be compiled when it was invoked with a type that has a "status" property.
All the same applies to the Param type argument. The usefulness of a generic method here rapidly disappears when you do this, it is not the proper usage. Unless you can leverage IResult, like you can IEnumerable.
Compiles...
You ought to descibe what you aim is in your question.
See Hans' answer for details that might help you understand the error.
Your problem is that you're saying the function should take a Result that is instantiable, but you are not saying it has to have a property called "status".
namespace chsarp
{
class Program
{
static void Main(string[] args)
{
Func<int, string> m = Test.GetStatus;
var t = TestFn(m, 10);
}
static string TestFn<TParam>(Func<TParam, string> m, TParam p)
{
try { return m(p); }
catch (Exception exception)
{
return string.Format("Reserving \"{0}\" failure exception: {1}", p, exception);
}
}
}
static class Test
{
public static string GetStatus(int inp)
{
return string.Format("The ReservationID-{0}", inp);
}
}
}