Is injecting a model into a service an anitipattern - robotlegs

Some services in my Robotlegs app require parameters. I'm wondering which solution is better:
Mediators pass parameters to services
Services aquire parameters from injected models

As Creynders suggested, it depends on the scope of these variables, if they are const, model, or user input.
A great resource for me has been the ActionScript Developer's Guide to RobotLegs: http://books.google.ca/books/about/ActionScript_Developer_s_Guide_to_Robotl.html?id=PFA2TWqZdSMC&redir_esc=y
This is my usual workflow:
View dispatches a custom event and passes parameters to the event.
Mediator listens to the Event and re-dispatches it.
Context maps the event to a command.
Command injects the event, any necessary models, and the service.
Command calls the service, passing any necessary parameters. In the example below, I am passing a variable from the LoadLicenseEvent and from the ITokenModel to the service call. I use commandMap.detain() and commandMap.release() to keep the command alive until the service call is complete. The base class ServiceModuleCommand handles the fault event.
public class LoadLicenseCommand extends ServiceModuleCommand
{
[Inject]
public var event:LoadLicenseEvent;
[Inject]
public var service:ILicenseService;
[Inject]
public var tokenModel:ITokenModel;
[Inject]
public var licenseModel:ILicenseModel;
public override function execute():void
{
commandMap.detain(this);
var token:TokenVO = tokenModel.getToken();
var asyncToken:AsyncToken = service.getLicense(token.Id, event.id);
asyncToken.addResponder(new mx.rpc.Responder(resultHandler, faultHandler));
}
private function resultHandler(e:ResultEvent):void
{
var license:LicenseWebViewVO = e.result as LicenseWebViewVO;
if (license)
{
licenseModel.license = license;
dispatchToModules(new RunWidgetEvent(WidgetType.getWidgetId(WidgetType.LICENSE)));
}
commandMap.release(this);
}

Related

Is there a way to avoid using magic strings with the HubConnection class

I have a strongly typed Hub on the server:
public Foo : Hub<Bar> {}
Bar is supposed to be an interface including methods available on the client side. But that solves only half of the problem (the server half). On the client side, I still have to use magic strings to define handlers for calls to the methods of Bar:
hubConnection.On<int>("MethodInsideBar", param => DoSomething(param));
Is there a way to avoid doing this ? Shouldn't there be a way to implement Bar client side and link the calls from the server to that implementation ?
You can use the SignalR.Strong NuGet
Sample Code:
Foo.cs
public interface IBar
{
Task MethodInsideBar(int n);
}
public class Foo : Hub<IBar> {}
Client.cs:
public class MySpoke : IBar
{
public Task MethodInsideBar(int n)
{
//
return Task.CompletedTask;
}
}
var conn = new SignalR.Client.HubConnection()
.WithUrl("http://localhost:53353/MyHub")
.Build();
await conn.StartAsync();
var registration = conn.RegisterSpoke<IBar>(new MySpoke())
BlazorPage.razor
#using Microsoft.AspNetCore.SignalR.Client
#using SignalR.Strong
#inject NavigationManager Nav
#implements IBar
#code {
private HubConnection? hubConnection;
public Task MethodInsideBar(int n)
{
//
return Task.CompletedTask;
}
protected override async Task OnInitializedAsync()
{
hubConnection = new HubConnectionBuilder()
.WithUrl(Nav.ToAbsoluteUri("/foo"))
.WithAutomaticReconnect()
.Build();
await hubConnection.StartAsync();
hubConnection.RegisterSpoke<IBar>(this);
await base.OnInitializedAsync();
}
}
server.cs
public class FooBar
{
private readonly IHubContext<Foo, IBar>? _hubContext;
// dependency injected IHubContext
public FooBar(IHubContext<Foo, IBar>? hubContext)
{
_hubContext = hubContext;
}
public void CallBar(int n)
{
_hubContext?.Clients.All.MethodInsideBar(n);
}
}
On the client side, I still have to use magic strings to define
handlers for calls to the methods of Bar:
hubConnection.On<int>("MethosInsideBar", param => DoSomething(param));
Is there a way to avoid doing this ? Shouldn't
there be a way to implement Bar client side and link the calls from
the server to that implementation ?
As far as I know, the Strongly typed hubs only apply to the server side, we could inject the strongly-typed HubContext in the controller, then, call the hub method. It can prevent the method name is misspelled or missing from the client.
On the client side, we still need to use the Invoke method call the public methods on hubs, and define a method using the on method of the HubConnection to receive messages from the hub.
When calling the public hub methods from client, if you want to use the Strongly typed Hubs, you could inject the Strongly typed hubcontext into the controller, then use JQuery Ajax call the controller's action method, then use the Strongly typed hubs method. Refer this thread: SignalR - Call statically typed hub from Context.

Blazor. Task from another service

I'm studying blazor server.
Deployed a solution from a standard vs template.
Created two server-side services, TestService1 and TestService2.
In TestService1 i have task
GetMyData()
How can i call with task from TestService2?
If i trying
var serv1 = new TestService1()
i have to fill in all the variables of the constructor that is in TestService1.
What is easiest way?
In line with the comment on your question, the best way to go about this in Blazor is to utilize the built-in dependency injection mechanism.
I assume that your services look like the following:
public class TestService1
{
public object GetMyData()
{
}
}
public class TestService2
{
private readonly TestService1 _testService1 { get; set; }
public class TestService2(TestService1 ts1)
{
_testService1 = ts1;
}
public void DoesSomething()
{
var data = _testService1.GetMyData();
//...
}
}
First, you'd need to register these with Blazor at startup, so in your Startup.cs in the ConfigureServices method, add the following, assuming you have an empty constructor available for TestService1:
services.AddSingleton<TestService1>();
Because you'll need to instantiate an instance of TestService1 into TestService2 to call methods on it, you'll have to handle registration of TestService2 differently since you'll need to procure an instance of TestService1 from the DI service to instantiate it:
services.AddSingleton<TestService2>(s => {
var testService1 = s.GetService<TestService1>();
return new TestService2(testService1);
});
It's possible you may need to scope the services differently (e.g. used scoped instead of singletons). You can read about the differences here.
Now something is presumably calling TestService2 to kick all this off, so let's pretend it's running in a component in your Blazor app. You'd inject TestService2 into the component with the following:
#inject TestService2 _testService2
<h1>Hello!</h1>
#code {
protected override void OnInitialized()
{
_testService2.DoesSomething();
}
}
As part of the initialization then of this component, it'll automatically inject a TestService2 instance (based on the scoping you specified at DI initialization) to your component and will call the DoesSomething method on it. When injected, it looks to DI to instantiate the TestService1 service to the constructor as you've also specified, leaving it free to call that method and the call commences as intended.
Please let me know if you'd like any clarification somewhere!

Injecting DbContext in constructor of Web api 2 controller

I am creating a small proof of concept asp.net web api 2 service with entity framework code first. The controller's constructor looks like
public AccountController: ApiController
{
private readonly DbContext context;
public AccountController(DbContext _context){
context = _context;
}
public AccountController(){context = new ApplicationContext();}
}
I need to unit test my controllers. How can I mock the DbContext class. Is there a simple way of doing this? I want to avoid all that repository pattern with lot of interfaces. Because it will be a way overkill for this prototype.
Its usually something like this if you use Nunit and Moq.
[TestFixture]
public class AccountControllerTest
{
private Mock<DbContext> mockContext;
private AccountController sut;
[SetUp]
public void TestSetup()
{
mockContext = new Mock<DbContext>();
var account = new Account() { Id = 123, Name = "Test Account" };
mockContext.SetUp(x => x.GetAccountOnContext()).Returns(account);
sut = new Controller(mockContext.Object) { Request = new HttpRequestMessage() };
sut.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());
}
[Test]
public void ControllerMethod_GetLogin_Test()
{
// assuming GetLogin calls GetAccount on DbContext()
var response = sut.GetLogin(someAccount);
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
mockContext.Verify();
}
}
You basically want to mock out your external dependencies and test just what the SUT (System Under Test) is supposed to do. I would also strongly encourage to look at Fakes instead of mocks. In general fakes result in less brittle tests.
So in this case, you could have a FakeDbContext() that you can pass to the tests. The FakeDbContext() will behave more like the actual DbContext() but will do all those operations in-memory, so that your tests don't have a dependency with a real database.
Depending on the database you use, you can also look at starting an embedded version of the real database as a part of your tests. Just have to make sure to do the necessary stopping and clean up of the test database records after the test run is complete in the TearDown() method.

How to separate remote object and interface in Flash Builder Flex

The code below shows interface and remote object are coded in the same file How to separate them into two files ?
Current Code :
<s:RemoteObject id="ro"
destination="customerService"
source="customerService"
endpoint="http://localhost/amfphp/gateway.php"
showBusyCursor="true">
<s:method name="getCustomer" result="getCustomer_resultHandler(event)">
<s:arguments>
<CusOpt>{''}</CusOpt>
<option>{''}</option>
<idcompany>{2}</idcompany>
</s:arguments>
</s:method>
<s:method name="genPKID" result="genPKID_resultHandler(event)">
<s:arguments>
<idcompany>{2}</idcompany>
</s:arguments>
</s:method>
</s:RemoteObject>
Wrong way of doing :
import mx.rpc.remoting.RemoteObject;
public class CustomerRO extends RemoteObject
{
public function CustomerRO(destination:String=null)
{
super(destination);
this.destination = "customerService";
this.source = "customerService";
this.endpoint = "http://localhost/amfphp/gateway.php";
this.showBusyCursor = true;
}
}
You want to create a client-side service stub for your remote service. There's a few steps to get this set up properly.
Create the service interface
For brevity we'll create an interface with just one method, but you can add as many as you need.
package be.vmm.user.service {
import mx.rpc.AsyncToken;
public interface ICustomerService{
function getCustomerById(id:int):AsyncToken;
}
}
Create an implementation of the interface
In your example you are extending RemoteObject. I would suggest you encapsulate it: that would be a lot more flexible. Not to mention that in your code the connection information is hardcoded which requires you to recompile your application every time this info changes.
public class CustomerService implements ICustomerService {
private var ro:RemoteObject;
public function CustomerService(ro:RemoteObject) {
this.ro = ro;
}
public function getCustomerById(id:int):AsyncToken {
return ro.getCustomerById(id);
}
}
You also have the option to create another implementation of the interface. The most common use case consists of creating a mock service that doesn't really connect to the server but returns fake data directly. If you want to test your application without server connection you can now just substitute your real service stub with the mock service stub, since they both implement the same interface.
Use the implementation
var ro:RemotObject = new RemoteObject();
ro.destination = "customerService";
ro.source = "customerService";
ro.endpoint = "http://localhost/amfphp/gateway.php";
ro.showBusyCursor = true;
//these properties are best externalized in a configuration file
var service:ICustomerService = new CustomerService(ro);
var token:ASyncToken = service.getCustomerById(1);
token.addResponder(new Responder(handleResult, handleFault));
private function handleResult(event:ResultEvent):void {
//do what you need to do
trace(event.result as Customer);
}
private function handleFault(event:FaultEvent):void {
//show error message
}

Verifying indirectly called methods with Moq on a mocked object

My app has a ProviderFactory static class that has static utility methods passing back static instances of things like a logger. The rest of my app then can just grab a/the reference to the logger from anywhere without having to pass in the logger (common design practice).
So, another part of my app, the DbCacheProvider, has methods that make calls to the logger so internally it gets a reference to the logger from the factory and then issues calls to it.
My question is that using Moq, I want to verify methods on the logger are being called by the methods within the DbCacheProvider. I can do this using dependency injection when I pass a mock logger into the DbCacheProvider as a parameter, but I'm not passing the logger in (not do I want to). So, how would I verify the DbCacheProvider is making calls to the logger?
If you don't want to pass the logger in through the constructor you'd need to change your ProviderFactory while running unit tests to return your mocked logger.
Anyway there are a couple of reasons it's often suggested to set up dependency injection:
Your tests are more straightforward and don't involve finagling with custom factories
IoC frameworks like Unity, Ninject and Autofac make it easy to create objects when their dependencies are set up this way. If you set up all of your objects this way, the framework will do all the heavy lifting of creating the right objects and passing them in for you. The dependency injection is done automatically and won't be a burden for you.
Old question without an answer, I had a similar problem and solved it like this:
I have the following sample code and need to verify that not only was a method called but was called with a specific value.
public interface ILog
{
void Info(string message);
}
public interface ILogFactory
{
ILog GetLogger();
}
This is the class being tested, where the interface items are being injected:
public class NewAction
{
readonly ILogFactory _logger;
public NewAction(ILogFactory logger)
{
_logger = logger;
}
public void Step1()
{
_logger.GetLogger().Info("Step 1");
}
public void Step2()
{
_logger.GetLogger().Info("Step 2");
}
}
This is obviously a very simplistic view of my actual code, but I needed to verify that Step1 and Step2 are behaving as expected and passed the correct values to the Log, this would mean I also needed to ensure they occurred in the right order. My test:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
// Arrange
var log = new Mock<ILog>();
var factory = new Mock<ILogFactory>();
factory.Setup(l => l.GetLogger()).Returns(log.Object);
// Act
var action = new NewAction(factory.Object);
action.Step1();
action.Step2();
// Assert
factory.Verify(l => l.GetLogger());
log.Verify(l => l.Info(It.Is<string>(s => s == "Step 1")));
log.Verify(l => l.Info(It.Is<string>(s => s == "Step 2")));
}
}
Hope this helps.

Resources