mock domain class created by another domain class with spock - unit-testing

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 ->
}

Related

Can't read variables from application.properties

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.

Why Spock's Interactions doesn't work for Mock that built by other class

I'm trying to assemble all Mock building methods in one class.
but when I use Mock object that built by building method on other groovy class .
the stubbing of Mock seems work fine , but interactions check doesn't work.
well ... how should I achieve this ?
MockTestingSpec.groovy
class MockTestingSpec extends Specification{
def "use mock from other class"(){
setup:"construct mock builder"
def bldr = new MockBuilder()
when:"build mock by MockBuilder"
def mockObj = bldr.buildMock()
and:"build mock by private method of this class"
def builtAtThisClass = buildMock()
then:"check stubbing are working. these conditions were satisfied"
mockObj.getKey().equals("keyyyy")
mockObj.getValue() == 12345
builtAtThisClass.getKey().equals("keyyyy")
builtAtThisClass.getValue() == 12345
when:"put a mock to private method"
callMockGetter(builtAtThisClass)
then:"call each getter, these conditions were also satisfied"
1 * builtAtThisClass.getKey()
1 * builtAtThisClass.getValue()
when:"puta a mock that built by builder"
callMockGetter(mockObj)
then:"these conditions were NOT satisfied... why?"
1 * mockObj.getKey()
1 * mockObj.getValue()
}
// completely same method on MockBuilder.
private buildMock(String key = "keyyyy",Integer value = 12345){
TestObject obj = Mock()
obj.getKey() >> key
obj.getValue() >> value
return obj
}
private callMockGetter(TestObject obj){
obj.getKey()
obj.getValue()
}
}
MockBuilder.groovy
class MockBuilder extends Specification{
public buildMock(String key = "keyyyy",Integer value = 12345){
TestObject obj = Mock()
obj.getKey() >> key
obj.getValue() >> value
return obj
}
public static class TestObject{
private String key
public String getKey(){
return key
}
private Integer value
public Integer getValue(){
return value
}
}
}
Moving mock creation to a superclass works instead. This way you can reuse complex mock creation across multiple Specs.
abstract class MockCreatingSpec extends Specification {
createComplexMockInSuperClass() {
return Mock()
}
}
class MockTestingSpec extends MockCreatingSpec {
def "use mock from superclass"() {
given:
def mock = createComplexMockInSuperClass()
...
}
}

Sitecore Glass data model inheritence

I am using the Glass Mapper on a Sitecore instance where I have a basic data template structure of
Base
BaseWithList
BaseWithExtraContent
BaseWithExtraContentAndCallToActionLink
I have added model classes in my project to follow this structure too. My class names match my template names.
[SitecoreType(TemplateId = "{5D19BD92-799E-4DC1-9A4E-1DDE3AD68DAD}", AutoMap = true)]
public class Base
{
public virtual string Title {get;set;}
public virtual string Content {get;set;}
}
[SitecoreType(TemplateId = "{0491E3D6-EBAA-4E21-B255-80F0607B176D}", AutoMap = true)]
public class BaseWithExtraContent : Base
{
public virtual string ExtraContent {get;set;}
}
[SitecoreType(TemplateId = "{95563412-7A08-46A3-98CB-ABC4796D57D4}", AutoMap = true)]
public class BaseWithExtraContentAndCallToActionLink : BaseWithExtraContent
{
public virtual string CallToActionLink {get;set;}
}
These data models are used from another class that has a list of base type, I want to be able to store any derived type in here so I added attributes as detailed in this tutorial
[SitecoreType(AutoMap = true)]
public class HomePage
{
[SitecoreChildren(InferType = true)]
[SitecoreField(FieldName = "Widgets")]
public virtual IEnumerable<Base> Widgets { get; set; }
}
According to the tutorial this should work. However the list of widget just contains class of the base type.
I then found a later tutorial that said that if you have separated out the models to a different assemblies than the one Glass is installed in you have to add an AttributeConfigurationLoader pointing to the assembly your models are in. The base and derived types are all in the same assembly so I wasn't sure this would solve the issue, but I tried it anyway.
My custom loader config looks like this:
public static class GlassMapperScCustom
{
public static void CastleConfig(IWindsorContainer container)
{
var config = new Config {UseWindsorContructor = true};
container.Install(new SitecoreInstaller(config));
}
public static IConfigurationLoader[] GlassLoaders()
{
var attributes = new AttributeConfigurationLoader("Project.Data");
return new IConfigurationLoader[] {attributes};
}
public static void PostLoad(){
//Remove the comments to activate CodeFist
/* CODE FIRST START
var dbs = Sitecore.Configuration.Factory.GetDatabases();
foreach (var db in dbs)
{
var provider = db.GetDataProviders().FirstOrDefault(x => x is GlassDataProvider) as GlassDataProvider;
if (provider != null)
{
using (new SecurityDisabler())
{
provider.Initialise(db);
}
}
}
* CODE FIRST END
*/
}
}
Upon doing the custom loader config I now get an "Ambiguous match found" exception. I have checked to see if there are any other non Glass attributes set in the classes in that assembly and there aren't.
Any ideas? I guess there are 2 questions.
Why does using the inferred type attribute not load the correct types and only the base types?
Why when I attempt to solve this by adding a custom attribute loader do I get the exception?
Widgets property has two attributes - it's either mapped to the children elements of the item, or a field, can't be both.

Retrieve data from MockRepository?

I'm new to Unit Testing and I'm using Rhino Mock in ASP.NET MVC
I have created a main test class with this code :
[TestFixture]
public class PersistenceTest
{
[Test]
protected T SaveAndLoadEntity<T>(T entity) where T : BaseEntity
{
var mockDataSource = MockRepository.GenerateMock<IRepository<T>>();
mockDataSource.Add(entity);
var fromDb = mockDataSource.FindBy(entity.Id);
return fromDb;
}
}
and create a customer test class like this :
[TestFixture]
public class CustomerTests : PersistenceTest
{
[Test]
public void Can_Save_And_Load_Customer()
{
var customer = new Customer()
{
Id = 12,
Name = "Reza",
Family = "Pazooki",
Company = "Rozaneh",
Email = "ipazooki#gmail.com",
Mobile = "09352463668",
Fax = "021-44869059",
Tel = "021-44869059",
WebSite = "www.rozanehmedia.com"
};
var fromDb = SaveAndLoadEntity(customer);
fromDb.ShouldNotBeNull();
}
}
but when run the code, it says that return value from Database is NULL!!!
I don't know what is wrong with my code but I save and retrieve data from mock repository and it seems every thing is ok.
tnx form any help in forward :)
Mocks are used to record invocations on objects for further verification or to provide values when called (later behavior requires setup).
In your SaveAndLoadEntity method you make calls to mock (Add and FindBy). Since mock is a fake object with no real behavior, those calls do nothing (they don't save nor extract any entities to/from database).
If you want to test persistence layer you should be doing tests against real database instance (or optionally, in-memory one).
// [Test] attribute is not needed
protected T SaveAndLoadEntity<T>(T entity) where T : BaseEntity
{
var dataSource = new DataSource("connection string");
dataSource.Add(entity);
var fromDb = dataSource.FindBy(entity.Id);
return fromDb;
}
At the moment you are making calls to not-setup mock which doesn't achieve anything.
Thank you jimmy_keen.
I change my code according to your advice like this and it worked great :)
[TestFixture]
public class PersistenceTest
{
protected ISession Session;
protected ITransaction Transaction;
[SetUp]
public void SetUp()
{
var helper = new NHibernateHelper("...connectionString....");
Session = helper.SessionFactory.OpenSession();
Transaction = Session.BeginTransaction();
}
protected T SaveAndLoadEntity<T>(T entity) where T : BaseEntity
{
Session.Save(entity);
Transaction.Commit();
var fromDb = Session.Get<T>(entity.Id);
return fromDb;
}
}

How do I unit test a non-generic method that calls a generic method in a sealed non-generic class?

using [assembly:InternalsVisibleTo()] and
public sealed class AppService
{
//TODO: fix dev's spelling
//want to test this
public AddSubscribtionResponse AddSubscribtion(AddSubscribtionRequest request)
{
return ExecuteQueryProc<AddSubscribtionResponse>("spAddAppToUserGroup", request).First();
}
//I want to stub or interaction test the call to here
#if DEBUG
internal
#endif
List<T> ExecuteQueryProc<T>(string query, object parameters = null)
{
var cn=GetConnection();
//DatabaseCommand is a static class =(
return DatabaseCommand.ExecuteQueryProc<T>(cn, query, parameters);
}
}
Every attempt I've made at getting Rhino to stub or intercept the Execute Query proc method has failed.
var service = MockRepository.GeneratePartialMock<AppService>(null);
service.Stub(f => f.ExecuteQueryProc<AddSubscribtionRequest>(null, null)).IgnoreArguments().Return(new List<AddSubscribtionRequest>());
var expected = new AddSubscribtionRequest();
var actual = service.AddSubscribtion(expected);
Throws
System.InvalidOperationException: ExecuteReader: CommandText property has not been initialized
Remove the "sealed" from your class (Rhino.Mocks can't proxy your class if it can't inherit from it). And ExecuteQueryProc has to be virtual to be able to stub its functionality.