I am making a Spring application in which I'm sending data to kinesis. I have the accessKey and secretKey stored in application.properties. In the service implementation class I am using these variables but im getting an error that access key cannot be null.
The ProducerServiceImpl class:
public class ProducerServiceImpl extends ProducerService {
private static final Logger LOG = LoggerFactory.getLogger(ProducerServiceImpl.class);
#Value(value = "${aws.stream_name}")
private String streamName;
#Value(value = "${aws.region}")
private String awsRegion;
#Value(value = "${aws.access_key}")
private String awsAccessKey;
#Value(value = "${aws.secret_key}")
private String awsSecretKey;
private KinesisProducer kinesisProducer = null;
public ProducerServiceImpl() {
this.kinesisProducer = getKinesisProducer();
}
private KinesisProducer getKinesisProducer() {
if (kinesisProducer == null) {
BasicAWSCredentials awsCreds = new BasicAWSCredentials(awsAccessKey, awsSecretKey);
KinesisProducerConfiguration config = new KinesisProducerConfiguration();
config.setRegion(awsRegion);
config.setCredentialsProvider(new AWSStaticCredentialsProvider(awsCreds));
config.setMaxConnections(1);
config.setRequestTimeout(6000); // 6 seconds
config.setRecordMaxBufferedTime(5000); // 5 seconds
kinesisProducer = new KinesisProducer(config);
}
return kinesisProducer;
}
I think the reason is that because after the function, the constructor is called first, the variables are not being assigned the value from #Value.
If you're using the #Value annotation on fields, Spring will use field injection. This means that it first needs to create an instance of ProducerServiceImpl (by calling your constructor), and then it will use reflection to initialize those fields annotated with #Value.
So, since your constructor is invoked before the values are injected, they will be null.
There are two basic solutions, one is to use constructor injection:
public class ProducerServiceImpl extends ProducerService {
// ... Fields
// Pass #Value as constructor parameters
public ProducerServiceImpl(#Value(value = "${aws.access_key}") String awsAccessKey) {
// Set the fields before calling getKinesisProducer()
// If you only need the fields to create the producer, you could also just pass them as arguments to the getKinesisProducer() function
this.awsAccessKey = awsAccessKey;
this.kinesisProducer = getKinesisProducer();
}
// ...
}
The other solution is to wait until Spring has initialized the bean. This can be done by moving the logic to a method annotated with #PostConstruct:
public class ProducerServiceImpl extends ProducerService {
// ... Fields
// Replace the constructor by a method annotated with #PostConstruct
#PostConstruct
public void initializeKinesisProducer() {
this.kinesisProducer = getKinesisProducer();
}
// ...
}
However, the prefered solution is to move the entire KinesisProducer setup to a Spring configuration class, and provide it as a bean. Since all Spring beans are singletons, you can get rid of that initialization code. For example:
// Create a new #Configuration class
#Configuration
public class KinesisConfiguration {
// Create a #Bean method to construct your KinesisProducer
#Bean
// Pass all #Value's as parameters
public KinesisProducer kinesisProducer(#Value("${aws.access_key} String awsAccessKey) {
BasicAWSCredentials awsCreds = new BasicAWSCredentials(awsAccessKey, awsSecretKey); KinesisProducerConfiguration config = new KinesisProducerConfiguration();
config.setRegion(awsRegion);
config.setCredentialsProvider(new AWSStaticCredentialsProvider(awsCreds));
config.setMaxConnections(1);
config.setRequestTimeout(6000); // 6 seconds
config.setRecordMaxBufferedTime(5000); // 5 seconds
return new KinesisProducer(config);
}
}
Now you can delete all that code in your service and use:
public class ProducerServiceImpl extends ProducerService {
// Inject your KinesisProducer, either through field injection or constructor injection
#Autowired
private KinesisProducer kinesisProducer;
}
I would suggest moving your #Value configuration properties to another class using #ConfigurationProperties and inject that in your constructor.
Related
I have a dotnet 3.1 core web api application and looking to use xUnit. In this, I am only wanting to test the public methods, BUT I do have several private methods that either make a call to a database to return data or make a rest call to an external service.
Question:
I am NOT trying to test the private method, but how can I fake the return data of the private methods, so that when my public method calls the private method, I can return a fake set of data so that my public method and calculations can be tested?
Thanks in advance!
Update
Here is an example of what I am trying to do.
public class FooRepository{
public MyObject CalculateValues{
var myReturnObject = new MyObject();
var crewSalaries = GetCrewSalaries(myCrew)
myObject.TotalSalary = crewSalaries.Sum(x=>x.salary)
// Insert other calculations here
}
private MyObject GetCrewSalaries(List<Crew> myCrew){
return dbContext.Where(x=>x.id == myCrew.id).ToList();
}
}
Public Class FooRepositoryTest{
[Fact]
public Test1()
{
var fooClass = new fooClass();
// mock or hijack fooClass.GetCrewSalaries, so that I can return fake data
var result = fooClass.CalculateValues();
// assert statement here
}
private GetFakeSalaryData()
{
return new List<CrewSalaries>{
[
id:1,
salary:23
],
[
id:2,
salary:23.1
],
}
}
}
Consider the following
ClassA has a constructor that takes an instance of MasterClass and a string and exposes a property called Names of type string[].
ClassB has a constructor that takes an IJuicePresser and a IEnumerable<string>.
ClassC has a constructor that takes an IEnumerable<string>.
Manually I would do something like this to tie them together.
var masterClass = new MasterClass();
var juicePresser = JuicePresser.Create("default");
var classA = new ClassA(masterClass, "string");
var names = classA.Names;
var classB = new ClassB(juicePresser, names as IEnumerable<string>);
var classC = new ClassC(Array.Reverse(names));
How can I set up DryIoc to handle these registrations/resolutions for me?
It might be better to move all these run-time names from constructors to corresponding methods. But here is the matching DryIoc setup as-is:
Live on .NET Fiddle
using System;
using System.Collections.Generic;
using System.Linq;
using DryIoc;
public class Program
{
public static void Main()
{
var c = new Container();
c.Register<MasterClass>();
c.Register<JuicePresser>(Made.Of(() => JuicePresser.Create("default")));
// an example how to inject a primitive value: "string" in this case
c.Register<ClassA>(made: Parameters.Of.Type<string>(_ => "string"));
// service key is optional, just to distinguish the list of strings for consumer.
c.Register<string[]>(
Made.Of(_ => ServiceInfo.Of<ClassA>(), factory => factory.Names),
serviceKey: "names");
// register reverse names using ReverseHelper method
c.Register<string[]>(
Made.Of(() => ReverseHelper(Arg.Of<string[]>("names"))),
serviceKey: "reverse-names");
// specify the names and required type (string[]) for injection
c.Register<ClassB>(made: Parameters.Of.Type<IEnumerable<string>>(typeof(string[]), serviceKey: "names"));
// specify reverse names for injection
c.Register<ClassC>(made: Parameters.Of.Type<string[]>(serviceKey: "reverse-names"));
var classB = c.Resolve<ClassB>();
var classC = c.Resolve<ClassC>();
Console.WriteLine(string.Join(" - ", classB.Names.ToArray()));
// outputs: a - string - z
Console.WriteLine(string.Join(" - ", classC.Names));
// outputs: z - string - a
}
public static T[] ReverseHelper<T>(T[] target) {
Array.Reverse(target);
return target;
}
public class MasterClass {}
public class JuicePresser
{
public readonly string Name;
private JuicePresser(string name) { Name = name; }
public static JuicePresser Create(string name)
{
return new JuicePresser(name);
}
}
public class ClassA
{
public readonly string[] Names;
public ClassA(MasterClass master, string name) {
Names = new[] { "a", name, "z" }; // for example
}
}
public class ClassB
{
public readonly JuicePresser Presser;
public readonly IEnumerable<string> Names;
public ClassB(JuicePresser presser, IEnumerable<string> names) {
Presser = presser;
Names = names;
}
}
public class ClassC
{
public readonly string[] Names;
public ClassC(string[] names) {
Names = names;
}
}
}
Update:
Explaining a bit the part with:
c.Register<string[]>(
Made.Of(_ => ServiceInfo.Of<ClassA>(), factory => factory.Names),
serviceKey: "names");
DryIoc has support for using not only constructors for service creation, but also static and instance methods (factory methods), properties and fields. Here is the wiki topic.
In example above we use Names property of ClassA object as factory method to register service type "string[]" with service key "names".
Let's see in detail:
// Registering service of ClassA. It means that it can be resolved / injected directly,
// or/and we can use it as a factory for resolving further services
c.Register<ClassA>(made: Parameters.Of.Type<string>(_ => "string"));
// Registering service of type "string[]"
c.Register<string[]>(
// Made.Of enables specifying factory method to use for "string[]" resolution, instead default constructor selection rules.
Made.Of(
// 1) Specifying what factory object should be used,
// Here we say to use ClassA service registered in container
requestNotUsedHere => ServiceInfo.Of<ClassA>(),
// 2) Specify that Names property of resolved ClassA object
// should be used for "string[]" resolution
classA => classA.Names),
// As the "string[]" is not very distinctive (unique) service type
// (you might register other "string[]" with different meaning),
// we identify the names with "names" service key. So when injected or
// resolved, you need to specify the service key in addition to type.
serviceKey: "names");
If you want to register with static factory method, property, field, then you don't need to specify request => ServiceInfo.Of<TFactory>() part. BTW, request parameter can be used for conditional selection of factory.
I am working on a unit test of an instance method. The method happens to be an ASP.NET MVC 4 controller action, but I don't think that really matters much. We just found a bug in this method, and I'd like to use TDD to fix the bug and make sure it doesn't come back.
The method under test calls a service which returns an object. It then calls an internal method passing a string property of this object. The bug is that under some circumstances, the service returns null, causing the method under test to throw a NullReferenceException.
The controller uses dependency injection, so I have been able to mock the service client to have it return a null object. The problem is that I want to change the method under test so that when the service returns null, the internal method should be called with a default string value.
The only way I could think to do this is to use a mock for the class under test. I want to be able to assert, or Verify that this internal method has been called with the correct default value. When I try this, I get a MockException stating that the invocation was not performed on the mock. Yet I was able to debug the code and see the internal method being called, with the correct parameters.
What's the right way to prove that the method under test calls another method passing a particular parameter value?
I think there's a code smell here. The first question I'll ask myself in such a situation is, is the "internal" method really internal/ private to the controller under test. Is it the controller's responsibility to do the "internal" task? Should the controller change when the internal method's implementation changes? May be not.
In that case, I would pull out a new targeted class, which has a public method which does the stuff which was until now internal to the controller.
With this refactoring in place, I would use the callback mechanism of MOQ and assert the argument value.
So eventually, you will end up mocking two dependancies:
1. The external service
2. The new targeted class which has the controller's internal implementation
Now your controller is completely isolated and can be unit tested independently. Also, the "internal" implementation becomes unit testable and should have its own set of unit tests too.
So your code and test would look something like this:
public class ControllerUnderTest
{
private IExternalService Service { get; set; }
private NewFocusedClass NewFocusedClass { get; set; }
const string DefaultValue = "DefaultValue";
public ControllerUnderTest(IExternalService service, NewFocusedClass newFocusedClass)
{
Service = service;
NewFocusedClass = newFocusedClass;
}
public void MethodUnderTest()
{
var returnedValue = Service.ExternalMethod();
string valueToBePassed;
if (returnedValue == null)
{
valueToBePassed = DefaultValue;
}
else
{
valueToBePassed = returnedValue.StringProperty;
}
NewFocusedClass.FocusedBehvaior(valueToBePassed);
}
}
public interface IExternalService
{
ReturnClass ExternalMethod();
}
public class NewFocusedClass
{
public virtual void FocusedBehvaior(string param)
{
}
}
public class ReturnClass
{
public string StringProperty { get; set; }
}
[TestClass]
public class ControllerTests
{
[TestMethod]
public void TestMethod()
{
//Given
var mockService = new Mock<IExternalService>();
mockService.Setup(s => s.ExternalMethod()).Returns((ReturnClass)null);
var mockFocusedClass = new Mock<NewFocusedClass>();
var actualParam = string.Empty;
mockFocusedClass.Setup(x => x.FocusedBehvaior(It.IsAny<string>())).Callback<string>(param => actualParam = param);
//when
var controller = new ControllerUnderTest(mockService.Object, mockFocusedClass.Object);
controller.MethodUnderTest();
//then
Assert.AreEqual("DefaultValue", actualParam);
}
}
Edit: Based on the suggestion in the comments to use "verify" instead of callback.
Easier way to verify the parameter value is by using strict MOQ behavior and a verify call on the mock after system under test is executed.
Modified test could look like below:
[TestMethod]
public void TestMethod()
{
//Given
var mockService = new Mock<IExternalService>();
mockService.Setup(s => s.ExternalMethod()).Returns((ReturnClass)null);
var mockFocusedClass = new Mock<NewFocusedClass>(MockBehavior.Strict);
mockFocusedClass.Setup(x => x.FocusedBehvaior(It.Is<string>(s => s == "DefaultValue")));
//When
var controller = new ControllerUnderTest(mockService.Object, mockFocusedClass.Object);
controller.MethodUnderTest();
//Then
mockFocusedClass.Verify();
}
"The only way I could think to do this is to use a mock for the class under test."
I think you should not mock class under test. Mock only external dependencies your class under test has. What you could do is to create a testable-class. It would be a class which derives from your CUT and here you can catch the calls to the another method and verify it's parameter later. HTH
Testable class in the example is named MyTestableController
Another method is named InternalMethod.
Short example:
[TestClass]
public class Tests
{
[TestMethod]
public void MethodUnderTest_WhenServiceReturnsNull_CallsInternalMethodWithDefault()
{
// Arrange
Mock<IService> serviceStub = new Mock<IService>();
serviceStub.Setup(s => s.ServiceCall()).Returns((ReturnedFromService)null);
MyTestableController testedController = new MyTestableController(serviceStub.Object)
{
FakeInternalMethod = true
};
// Act
testedController.MethodUnderTest();
// Assert
Assert.AreEqual(testedController.SomeDefaultValue, testedController.FakeInternalMethodWasCalledWithThisParameter);
}
private class MyTestableController
: MyController
{
public bool FakeInternalMethod { get; set; }
public string FakeInternalMethodWasCalledWithThisParameter { get; set; }
public MyTestableController(IService service)
: base(service)
{ }
internal override void InternalMethod(string someProperty)
{
if (FakeInternalMethod)
FakeInternalMethodWasCalledWithThisParameter = someProperty;
else
base.InternalMethod(someProperty);
}
}
}
The CUT could look something like this:
public class MyController : Controller
{
private readonly IService _service;
public MyController(IService service)
{
_service = service;
}
public virtual string SomeDefaultValue { get { return "SomeDefaultValue"; }}
public EmptyResult MethodUnderTest()
{
// We just found a bug in this method ...
// The method under test calls a service which returns an object.
ReturnedFromService fromService = _service.ServiceCall();
// It then calls an internal method passing a string property of this object
string someStringProperty = fromService == null
? SomeDefaultValue
: fromService.SomeProperty;
InternalMethod(someStringProperty);
return new EmptyResult();
}
internal virtual void InternalMethod(string someProperty)
{
throw new NotImplementedException();
}
}
What is the best way to implement "/schema" function on custom controllers (explained in rest-bucks ) similar to "[repository]/schema" function with Spring Data Rest?
If entity classes are persisted through Spring Repositories, the solution is to inject PersistentEntityToJsonSchemaConverter into the controller and invoke convert() method.
Below is a code sample using Mongo as Repository
Entity class
#Document
public class Project implements Identifiable<String> {
#Id
private String id;
#NotNull
private String name;
//getters setters
}
Repository
public interface ProjectRepository extends
PagingAndSortingRepository<Project, String> {
}
Controller
#Controller
#ExposesResourceFor(Project.class)
#RequestMapping("/projects")
public class ProjectController {
#Autowired
private PersistentEntityToJsonSchemaConverter jsonSchemaConverter;
#RequestMapping(value = "/schema", method = RequestMethod.GET, produces = { "application/schema+json" })
#ResponseBody
public JsonSchema schema() {
return jsonSchemaConverter.convert(Project.class);
}
// implement rest of SDR mechanics
}
I'm trying to test a domain class called EnityContact. Inside that class there is a method called initialize which populates some fields when needed. in order to do that the method creates instances of some other domain classes: AisUser, Entity and CPerson. AisUser is the domain class returned by the call to SecurityUtil.retrieveCurrentAisUser(false).
class EntityContact extends BaseObject implements Initializable{
....
#Override
void initialize() {
println "initaliazing"
isMain = false
creationDate = new Date()
createdBy = CPerson.get(SecurityUtil.retrieveCurrentAisUser(false).id)
entity = new Entity()
entity.setId(Long.valueOf(0)) //Id has to be initialized with some value
}
}
What i am trying to do is find a way to return mocks of those classes that i define in my specification.
Any ideas?
In Groovy you can mock static methods using MetaClass.
SecurityUtil.metaClass.'static'.retrieveCurrentAisUser = { boolean param ->
}