I have an integration test where I start an embedded MongoDB as a companion object. I want to reuse this piece of code and I am not sure if inheritance is the way to go (if possible).
It is a Spring Boot application:
This is my test:
#RunWith(SpringRunner::class)
#SpringBootTest
class RequestRepositoryTest {
#Autowired lateinit var requestRepository: RequestRepository
companion object {
private val starter = MongodStarter.getDefaultInstance()
private var _mongod: MongodProcess? = null
private var _mongo: MongoClient? = null
#BeforeClass
#JvmStatic fun beforeTest(){
val port = 27017
val _mongodExe = starter.prepare(MongodConfigBuilder()
.version(Version.Main.DEVELOPMENT)
.net(Net("localhost", port, Network.localhostIsIPv6()))
.build())
_mongod = _mongodExe.start()
_mongo = MongoClient("localhost", port)
}
#AfterClass
#JvmStatic fun afterTest(){
_mongod?.stop()
}
}
#Test
fun store() {
val id = requestRepository.store(Request(requestId = "123"))
assertNotNull(id)
}
}
My repository class:
#Repository
class RequestRepository #Autowired constructor(val datastore: Datastore)
{
fun store(request : Request) : String =
datastore.save(request).id.toString()
}
So my question is which is the 'correct' way to go about this in Kotlin.
Update edit: As an external object the test now looks a lot cleaner and the JUnit external resource is completely reusable across test classes:
Thanks #Lovis
#RunWith(SpringRunner::class)
#SpringBootTest
class RequestRepositoryTest {
companion object {
#ClassRule
#JvmField
val mongoServer = MongoServer
}
#Autowired lateinit var requestRepository: RequestRepository
#Test
fun store() {
val id = requestRepository.store(Request(requestId = "123"))
assertNotNull( id )
assertTrue { ObjectId.isValid(id) }
}
}
You should be able to achieve what you want using jUnit's #ClassRule and ExternalResource. No Kotlin magic needed :-)
Define an object in a separate File:
object MongoServer : ExternalResource() {
#Throws(Throwable::class)
override fun before() {
// before class
}
override fun after() {
// after class
}
}
Then use it within each test:
companion object {
#ClassRule
#JvmField
val mongoServer = MongoServer
}
The ClassRule annotation does the trick here, the companion object is necessary to make it static and the #JvmField annotation is necessary to make the field public. Those are restrictions by jUnit's rule system.
Related
I would like to write a Scala test which checks the exact class of an object created with factory method.
class Base { }
class Derived extends Base { }
class TestSpec {
test("test instance class") {
val result = new Derived()
// I want to check that result is exactly Derived type
result should be a[Derived]
result should not be a[Base]
}
}
I'm looking for something to test if object returned from my factory method for specific parameters is always base class. So it would be something like this is C#:
public class Base { }
public class Derived : Base { }
public class Program
{
public static void Main(string[] args)
{
var baseObject = new Base();
var derivedObject = new Derived();
var baseResult = baseObject.GetType().IsSubclassOf(typeof(Base));
var derivedResult = derivedObject.GetType().IsSubclassOf(typeof(Base));
Console.WriteLine(string.Format("Base is subclass of Base: {0}\nDerived is subclass of Base: {1}", baseResult, derivedResult));
}
}
you can do this :
class A{}
class B extends A{}
val result = new B()
result.getClass.getName shouldEqual classOf[B].getName
result.getClass.getName.equals(classOf[A].getName) shouldBe false
new Derived() will always be an instance of Base as it inherits from Base, which means:
new Derived().isInstanceOf[Base]
will return true.
But the opposite is false: Base won't be an instance of Derived.
Thus, to check if it's the Base class (and not the Derived class), you can use these two combined conditions:
new Base() should not be a[Derived]
new Base() shouldBe a[Base]
and to check if it's the Derived class, the following is enough:
new Derived() shouldBe a[Derived]
I have the following code...
class MyClassImpl extends MyClass {
#Autowired private val myService: MyService = null
...
override def deleteItem(id: String): Boolean = {
return myService.delete(id)
}
}
So I want to make a simple unit test to make sure it is calling the service.
#RunWith(classOf[MockitoJUnitRunner])
class MyClassImplTest(){
#Spy
#InjectMocks
var myClass: MyClassImpl = _
#Mock
var myService: myService = _
#Test
def testRun(){
doReturn(true).when(myService).delete(anyString())
myClass.deleteItem("");
verify(myService, times(1)).delete(anyString())
}
}
But when I run the test inside MyClassImplTest myService has a mocked object. However, inside MyClassImpl it is still null, so I get an NPE.
Can someone see what I am missing? Is this an idiosyncrasy of Scala?
I have play web application with conf/application.conf (nothing unusual). Guice is used for dependency injection. How can property value be injected in class constructor? The code is below.
class MyController #Inject() (private val foo: Foo) extends Controller {
...
}
#ImplementedBy(classOf[FooImpl])
trait Foo {
def bar: String
}
class FooImpl extends Foo {
override val bar = current.configuration.getString("my.bar").get
...
}
In the current configuration FooImpl can't be tested without running application. I want to be able instantiate FooImpl in unit tests. The perfect solution [from my point of view] should look like that:
class FooImpl #Inject() (#Named("my.bar") override val bar: String) extends Foo {
...
}
Unfortunately, this code doesn't work, because Guice doesn't have 'my.bar' binding:
No implementation for java.lang.String annotated with #com.google.inject.name.Named(value=my.bar) was bound.
The only solution that I came up with is writing my own module, which iterates through configuration properties and binds them as named dependencies (a variation of the example from this doc). But I believe that a better approach exists.
I implemented that using Java. I hope you can use it as reference for your Scala implementation.
At first, I created a Module:
public class MainModule extends AbstractModule {
public final static String TIMEOUT_IN_MILLISECONDS_ANNOTATION = "timeout-promise";
private final Configuration configuration;
public MainModule(#SuppressWarnings("unused") Environment environment, Configuration configuration) {
this.configuration = configuration;
}
#Override
protected void configure() {
long timeoutInMilliseconds = configuration.getLong("application.promise.timeout.in.milliseconds", 0L);
bindConstant().annotatedWith(Names.named(TIMEOUT_IN_MILLISECONDS_ANNOTATION)).to(timeoutInMilliseconds);
}
}
After that, I just used the annotation on different places:
class Service {
#Inject
#Named(MainModule.TIMEOUT_IN_MILLISECONDS_ANNOTATION)
protected long timeoutInMilliseconds;
}
Hope this helps.
Some time ago i was developed small guice extention for simple injection configuration variables mapped on Enum
guice-config
I encountered the same problem after about a year, and this time come up with the following solution (very similar to the one proposed by #stranger-in-the-q and #droidman):
class InjectionModule extends AbstractModule {
override def configure(): Unit = {
val config: Config = TypesafeConfigReader.config
config.entrySet().asScala.foreach { entry =>
val path = entry.getKey
entry.getValue.valueType() match {
case ConfigValueType.NUMBER =>
bind(classOf[Int])
.annotatedWith(Names.named(path))
.toInstance(config.getInt(path))
case ConfigValueType.BOOLEAN =>
bind(classOf[Boolean])
.annotatedWith(Names.named(path))
.toInstance(config.getBoolean(path))
case ConfigValueType.STRING =>
bind(classOf[String])
.annotatedWith(Names.named(path))
.toInstance(config.getString(path))
case _ =>
}
}
}
}
Also, this approach can be extended by appending prefixes to system properties (which key-value pairs are part of the loaded config):
private def getPrefix(configValue: ConfigValue): String = {
val description = configValue.origin().description()
if (description.contains("system properties")) {
"sys."
} else {
""
}
}
In this case instead of writing Names.named(path) one should use Names.named(getPrefix(entry.getValue) + path).
To inject multiple properties from a play configuration you could do this way. Create a map out of Play configuration and pass it as Properties to Guice binder.
public class Module extends AbstractModule {
private Environment environment;
private Configuration configuration;
public Module(Environment environment,Configuration configuration){
this.environment = environment;
this.configuration = configuration;
}
#Override
public void configure() {
Configuration helloConf = configuration.getConfig("myconfig");
Map<String, Object> map = helloConf.asMap();
Properties properties = new Properties();
properties.putAll(map);
Names.bindProperties(binder(), properties);
}
}
In JUnit you can use #ClassRule to annotate an static field.
How can I do this in Kotlin?
I tried:
object companion {
#ClassRule #JvmStatic
val managedMongoDb = ...
}
and
object companion {
#ClassRule #JvmField
val managedMongoDb = ...
}
but none of the last works because rule isn't executed.
I double checked that exactly same rule works fine without static context:
#Rule #JvmField
val managedMongoDb = ...
You are not using companion objects correctly. You are declaring an object (single instance of a class) called companion instead of creating a companion object inside of a class. And therefore the static fields are not created correctly.
class TestClass {
companion object { ... }
}
Is very different than:
class TestClass {
object companion { ... } // this is an object declaration, not a companion object
}
Although both are valid code.
Here is a correct working example of using #ClassRule, tested in Kotlin 1.0.0:
class TestWithRule {
companion object {
#ClassRule #JvmField
val resource: ExternalResource = object : ExternalResource() {
override fun before() {
println("ClassRule Before")
}
override fun after() {
println("ClassRule After")
}
}
}
#Test fun testSomething() {
println("Testing...")
}
}
This outputs:
ClassRule Before
Testing...
ClassRule After
How could I convert the following into scala.
public class JedisDB {
private static final JedisPool jedisPool = new JedisPool(getJedisPoolConfig());
public static JedisPoolConfig getJedisPool() {
// ..
}
public int getTest123() {
jedisPool.getResource();
// code goes here
}
}
I have seen answers do create a class and a companion object, but can someone explain to me exactly how and why I should do this?
Should I create what I want to expose as a static variable in the companion object, and the loading of the configuration file that is used to initialize the jedisPool in the class?
Do I have the option of making jedisPool public or private in the companion object?
Also (not to effect the answer to my question but as a added benefit), I read somewhere but didn't fully understand that this makes pattern makes testing difficult, are there workarounds then?
lazy val jedisPool : JedisPool = {
val poolConfig = createPoolConfig(app)
new JedisPool(poolConfig)
}
To get a resource
val j = jedisPool.getResource()
make sure you return resource after done using it.
jedisPool.returnResource(j)
Basically it does not metter if static methods will go to companion object or any other object. A companion object differs from other objects as it has access rights to the class/trait that other objects do not. But that's not really your's example.
Your sample with companion object:
// -- helpers to be able compile
class JedisPoolConfig { }
class JedisPool(p: JedisPoolConfig) {
def getResource = 1
}
// --
// everythis that should be SINGLETON goes into object
object JedisDB {
private lazy val jedisPool = new JedisPool(getJedisPool)
def getJedisPool = new JedisPoolConfig() // or any other implementation
def otherStaticMethod = new JedisDB().anyVal // wow - got access to private val.
}
class JedisDB {
import JedisDB._
def getTest123() = jedisPool.getResource
private val anyVal = "SomeValue";
// other methods
}
// other - non companion object
object JedisDB2 {
// def otherStaticMethod = new JedisDB().anyVal // no luck - no access
}